26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
53 #pragma package(smart_init)
72 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
73 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
74 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
75 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
76 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
77 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
88 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
89 AnsiString(TrainModeIn));
136 for(
int x = 0; x < 4; x++)
145 for(
int x = 0; x < 4; x++)
154 for(
int x = 0; x < 4; x++)
159 for(
int x = 0; x < 4; x++)
163 for(
int x = 0; x < 3; x++)
201 for(
int x = 0; x < 4; x++)
262 throw Exception(
"Error in attempting to delete FrontCodePtr");
266 for(
int x = 0; x < 4; x++)
270 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
275 for(
int x = 0; x < 4; x++)
279 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
308 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
374 bool TempDerail =
false;
420 else if((NextElementPosition > -1) && (NextEntryPos > -1))
491 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
501 for(
int x = 0; x < 4; x++)
508 for(
int x = 0; x < 4; x++)
769 int LockedVectorNumber;
899 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
900 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
901 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
902 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
903 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
904 "of a shortage of on train crew"};
911 if(DwellTime < TDateTime(30.0 / 86400))
913 DwellTime = TDateTime(30.0 / 86400);
915 int randval = random(10000);
920 if(randval < Utilities->MinorDelayCutoff)
927 if(randval < Utilities->ModerateDelayCutoff)
934 if(randval < Utilities->MajorDelayCutoff)
949 if(
NewDelay <
double(DwellTime) * 1440)
955 NewDelay -= double(DwellTime) * 1440;
1016 int randval2 = rand() % 24;
1017 AnsiString Reason = ReasonArray[randval2];
1020 " minutes because " + Reason);
1022 " minutes because " + Reason);
1028 " minutes because of a minor problem");
1030 " minutes because of a minor problem");
1182 if(BufferLocation ==
"")
1187 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1249 int NextElementPosition, NextEntryPos;
1273 NextElementPosition = -1;
1276 if((NextElementPosition > -1) && (NextEntryPos > -1))
1421 AnsiString StationName;
1432 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1442 if((NextElementPosition > -1) && (NextEntryPos > -1))
1590 if(TIFEntryPos == 0)
1627 if(NextElementPosition > -1)
1664 AnsiString Loc =
"";
1665 bool LocNamed =
false;
1694 Loc =
"outside railway";
1726 NextElementPosition = -1;
1737 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1755 if((NextElementPosition > -1) && (NextEntryPos > -1))
1793 FirstPair.second).
GetELink() == TempELink))
1798 SecondPair.second).
GetELink() == TempELink))
1812 FirstPair.second).
GetELink() == TempELink))
1817 SecondPair.second).
GetELink() == TempELink))
1831 FirstPair.second).
GetELink() == TempELink))
1836 SecondPair.second).
GetELink() == TempELink))
1866 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1869 int NewLastElement = 0, NewLastExitPos = 0;
1887 if(NewLastElement == -1)
1893 if(NewLastExitPos == -1)
1897 LastElement = NewLastElement;
1898 LastExitPos = NewLastExitPos;
1901 if(CumDistance < 1200)
1907 int FirstDistance = 0;
1908 if(CumDistance >= 1200)
1910 FirstDistance = 100;
1914 FirstDistance = 1200 - CumDistance;
1916 if(FirstDistance < 100)
1918 FirstDistance = 100;
1944 if(VectorIT->RouteNumber == RouteNumber)
1981 " failed when changing aspect.\nTrains can only pass under signaller control.");
2015 LockedVectorNumber)))
2174 for(
int x = 0; x < 4; x++)
2181 for(
int x = 0; x < 4; x++)
2207 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2212 if(OtherTrainEntryPos == -1)
2214 throw Exception(
"Error - OtherTrainEntryPos not set");
2233 int OtherTrainID = -1;
2234 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2325 bool StopRequired =
false;
2340 int NextElementEntryPos = -1;
2341 int NextElementExitPos = -1;
2342 bool TrainOnNextElement =
false;
2343 bool StopSignalAtNextElement =
false;
2344 if(ForwardConnection)
2352 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2354 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || TrainAtStopLinkPos3 || TrainAtStopLinkPos4 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2410 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2623 if(Code.Length() != 4)
2627 for(
int x = 1; x < 5; x++)
2634 for(
int x = 0; x < 4; x++)
2797 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2810 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2825 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2834 TRect SourceRect, DestRect;
2836 DestRect.init(0, 0, 8, 8);
2839 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2841 TempGraphic->PixelFormat = pf8bit;
2842 TempGraphic->Width = 16;
2843 TempGraphic->Height = 16;
2849 TempGraphic->Transparent =
true;
2853 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2854 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2860 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2868 else if(TempElement.
SpeedTag == 89)
2872 else if(TempElement.
SpeedTag == 90)
2876 else if(TempElement.
SpeedTag == 91)
2880 else if(TempElement.
SpeedTag == 92)
2884 else if(TempElement.
SpeedTag == 93)
2888 else if(TempElement.
SpeedTag == 94)
2892 else if(TempElement.
SpeedTag == 95)
2896 TempGraphic->Transparent =
true;
2900 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2901 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2903 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2910 for(
int x = 0; x < 40; x++)
2925 TempGraphic->Transparent =
true;
2929 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2930 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2932 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2946 TempGraphic->Transparent =
true;
2950 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2951 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2955 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2958 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2963 TempGraphic->Transparent =
true;
2967 int BDVectorPos = -1;
2976 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2981 TempGraphic->Transparent =
true;
2985 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2986 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2988 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2994 TempGraphic->Transparent =
true;
2998 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2999 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3001 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3267 throw Exception(
"Error, same train on two different bridge tracks");
3313 AnsiString(EntryPos) +
"," +
HeadCode);
3330 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3349 AnsiString(EntryPos) +
"," +
HeadCode);
3358 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3391 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3392 int LockedVectorNumber;
3405 TRect SourceRect, DestRect;
3406 DestRect.init(0, 0, 8, 8);
3413 int FirstELink, SecondELink = -1;
3416 if(RoutePair2.first > -1)
3425 if(SecondELink == -1)
3427 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3432 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3442 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3443 DestGraphic->PixelFormat = pf8bit;
3444 DestGraphic->Width = 8;
3445 DestGraphic->Height = 8;
3446 DestGraphic->Transparent =
true;
3449 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3458 PrefDirElement, LockedVectorNumber))
3473 if(ElementEntryPos > 1)
3495 AnsiString(EntryPos) +
"," +
HeadCode);
3497 bool WrongRoute =
false;
3523 int LinkNumber = TrackElement.
Link[EntryPos];
3524 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3529 bool LogActionErrorCalled =
false;
3539 LogActionErrorCalled =
true;
3556 else if(LinkNumber == 3)
3564 LogActionErrorCalled =
true;
3581 else if(LinkNumber == 7)
3589 LogActionErrorCalled =
true;
3606 else if(LinkNumber == 9)
3614 LogActionErrorCalled =
true;
3646 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3651 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3661 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3666 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3675 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3696 bool ColourError =
false, ColourError2 =
false;
3701 ColourError2 =
true;
3703 for(
int x = 0; x < 4; x++)
3708 ColourError2 =
true;
3714 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3718 for(
int x = 0; x < 4; x++)
3805 AnsiString(EntryPos) +
"," +
HeadCode);
3806 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3807 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3808 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3809 TrainInFrontInSignallerModeFlag =
false;
3810 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3811 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3812 bool SignallerStopRequired =
false;
3826 if(CurrentTrackVectorPosition > -1)
3830 if((EntryPos == 0) || (EntryPos == 2))
3843 else if(EntryPos == 1)
3867 EntryHalfLength = CurrentElementHalfLength;
3872 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3876 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3924 FrontElementMaxSpeed = LimitingSpeed;
3960 double ExitSpeedAtMaxBraking;
3965 ExitSpeedAtMaxBraking = 0;
3975 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3977 SpeedToUse = ExitSpeedAtMaxBraking;
3981 SpeedToUse = LimitingSpeed;
3996 RedSignalFlag =
false;
3997 BuffersFlag =
false;
3998 StationFlag =
false;
3999 BuffersOrContinuationNowFlag =
false;
4000 ContinuationNextFlag =
false;
4003 CumulativeLength += (2 * CurrentElementHalfLength);
4006 SignallerStopRequired =
true;
4028 bool StopRequired =
false;
4044 StationFlag =
false;
4050 BuffersOrContinuationNowFlag =
true;
4052 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4056 if((EntryPos == 0) || (EntryPos == 2))
4078 if(NextTrackVectorPosition > -1)
4083 if((NextEntryPos == 0) || (NextEntryPos == 2))
4096 else if(NextEntryPos == 1)
4109 if(NextEntryPos > 1)
4123 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4135 RedSignalFlag =
true;
4156 TrainInFrontInSignallerModeFlag =
true;
4181 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4193 double MaxHalfSpeed;
4197 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4199 MaxHalfSpeed = FrontElementMaxSpeed;
4203 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4211 bool HalfSpeedLimited =
false;
4215 HalfSpeedLimited =
true;
4245 if(HalfSpeedLimited)
4270 if(SignallerStopRequired)
4286 int TempMaxExitSpeed;
4289 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4291 MaxExitSpeedAtHalfBraking = 0;
4295 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4299 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4301 TempMaxExitSpeed = FrontElementMaxSpeed;
4305 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4317 if(ExitSpeedHalfSquared < 10)
4327 if(ExitSpeedFullSquared < 10)
4399 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4400 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4424 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4425 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4435 if(!BuffersOrContinuationNowFlag)
4437 if(NextSpeedLimit < LimitingSpeed)
4439 LimitingSpeed = NextSpeedLimit;
4443 int TempMaxExitSpeed;
4447 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4449 MaxExitSpeedAtHalfBraking = 0;
4453 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4455 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4457 TempMaxExitSpeed = FrontElementMaxSpeed;
4461 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4472 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4485 if(!BuffersOrContinuationNowFlag)
4487 CurrentTrackVectorPosition = NextTrackVectorPosition;
4488 EntryPos = NextEntryPos;
4489 CurrentElementHalfLength = NextElementHalfLength;
4492 ContinuationNextFlag =
true;
4496 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4516 if(ExitSpeedHalfSquared < 10)
4526 if(ExitSpeedFullSquared < 10)
4589 double DeltaExitTimeToMaxInSecs;
4590 double DistanceToMax;
4599 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4601 DistanceToMax = EntryHalfLength;
4604 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4605 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4622 double DeltaExitTimeToMaxInSecs;
4623 double DistanceToMax;
4632 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4634 DistanceToMax = EntryHalfLength / 2;
4637 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4638 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4649 if(ExitSpeedHalfSquared < 10)
4659 if(ExitSpeedFullSquared < 10)
4678 if((EntryPos == 0) || (EntryPos == 2))
4700 if(NextTrackVectorPosition > -1)
4702 int NextElementLength;
4703 if(NextEntryPos > 1)
4711 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4907 int ElementCount = 0;
4915 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4973 if((EntryPos == 0) || (EntryPos == 2))
4995 CurrentTrackVectorPosition = NextTrackVectorPosition;
4996 EntryPos = NextEntryPos;
4998 if(ElementCount > 1000)
5026 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
5051 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
5052 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
5053 int RouteStartPosition;
5055 int PlatformPosition;
5057 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5073 if(Distance > (4000 + LeadElementDistance))
5096 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5099 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5145 if(!PlatformFoundFlag)
5147 PlatformPosition = CurrentTrackVectorPosition;
5150 PlatformFoundFlag =
true;
5166 if((EntryPos == 0) || (EntryPos == 2))
5210 if(ElementNumber < 2)
5212 SkipRouteCheck =
true;
5216 SkipRouteCheck =
false;
5218 if(ElementNumber == 1)
5220 RouteStartPosition = CurrentTrackVectorPosition;
5230 if(ElementNumber > 1)
5234 RouteOrPartRouteSet =
true;
5238 RouteOrPartRouteSet =
false;
5241 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5248 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5249 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5261 Distance += CurrentTrackElement.
Length01;
5265 Distance += CurrentTrackElement.
Length23;
5267 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5268 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5269 CurrentTrackVectorPosition = NextTrackVectorPosition;
5270 EntryPos = NextEntryPos;
5307 return(RepeatHeadCode);
5329 bool FrontValid =
false, RearValid =
false;
5330 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5334 TrainToBeJoinedBy = NULL;
5348 int TrainToBeJoinedByID = -1;
5369 if((TrainToBeJoinedByID < 0) && RearValid)
5388 if(TrainToBeJoinedByID < 0)
5390 TrainToBeJoinedBy = NULL;
5395 if(!TrainToBeJoinedBy->
Stopped())
5397 TrainToBeJoinedBy = NULL;
5407 void TTrain::LogAction(
int Caller, AnsiString OwnHeadCode, AnsiString OtherHeadCode,
TActionType ActionType, AnsiString LocationName, AnsiString SplitDistribution,
5408 TDateTime TimetableNonRepeatTime,
bool Warning)
5444 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5445 AnsiString BaseLog =
"", WarningBaseLog =
"", ReminderBaseLog =
"", PerfLog =
"", ActionLog =
"";
5446 int IntMinsLate = 0;
5447 bool TTEvent =
false;
5452 ActionLog =
" arrived at ";
5462 ActionLog =
" terminated at ";
5468 ActionLog =
" departed from ";
5471 if(ActionType ==
Pass)
5473 ActionLog =
" passed ";
5478 ActionLog =
" created at ";
5480 if(ActionType ==
Enter)
5482 ActionLog =
" entered railway at ";
5486 ActionLog =
" changed its description to '" +
Description +
"' at ";
5489 if(ActionType ==
Leave)
5491 ActionLog =
" left railway at ";
5496 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from front to ";
5501 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from rear to ";
5506 ActionLog =
" joined by ";
5511 ActionLog =
" changed direction at ";
5516 ActionLog =
" became new service ";
5521 ActionLog =
" taken under signaller control at ";
5525 ActionLog =
" restored to timetable control at ";
5531 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5535 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5539 ActionLog =
" REMOVED FROM RAILWAY at ";
5544 ActionLog =
" received signaller authority to proceed";
5548 ActionLog =
" received signaller authority to step forward";
5552 ActionLog =
" changed direction under signaller control at ";
5556 ActionLog =
" received signaller authority to pass stop signal";
5560 ActionLog =
" received signaller instruction to stop";
5564 ActionLog =
" stopped on signaller instruction ";
5568 ActionLog =
" joined under signaller control by ";
5572 ActionLog =
" suffered an onboard power failure at ";
5576 ActionLog =
" failure repaired at ";
5580 ActionLog =
" left railway under signaller control at ";
5582 if(OtherHeadCode !=
"")
5584 OtherHeadCode +=
" at ";
5616 bool TimePerformance =
true;
5624 TimePerformance =
false;
5628 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5630 if(ActionType ==
Pass)
5644 IntMinsLate = int(ceil(MinsLate));
5648 IntMinsLate = int(floor(MinsLate));
5650 if(IntMinsLate == 0)
5652 PerfLog =
" on time";
5654 else if(IntMinsLate == 1)
5656 PerfLog =
" 1 minute late";
5658 else if(IntMinsLate == -1)
5660 PerfLog =
" 1 minute early";
5662 else if(IntMinsLate > 1)
5664 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5666 else if(IntMinsLate < -1)
5668 int PosIntMinsLate = -IntMinsLate;
5669 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5671 if(LocationName.Pos(
'-') > 0)
5673 PerfLog =
"," + PerfLog;
5686 if(ReminderBaseLog !=
"")
5689 ReminderBaseLog =
"";
5693 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5697 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5702 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5708 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5712 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5717 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5723 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5727 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5732 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5738 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5742 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5761 AnsiString LocName =
"";
5832 if(LocationName ==
"")
5836 int RearTrainRearPos, RearTrainFrontPos, RearTrainExitPos;
5837 int FrontTrainRearPos, FrontTrainFrontPos;
5840 if(LocationName ==
"")
5842 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5846 bool TemporaryDelay =
false;
5848 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
5872 AnsiString SplittingTrainDescription =
Description;
5879 for(
int x = 0; x < 4; x++)
5899 double NewTrainPowerAtRail;
5905 NewTrainMass =
Mass * double(MassPercent)/100.0;
5907 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
5908 if(NewTrainPowerAtRail == 0)
5910 NewTrainPowerAtRail = 0.08;
5918 NewTrainMass =
Mass;
5946 if(!SplitTrainExplicitDescription)
5991 if(LocationName ==
"")
5995 int RearTrainRearPos, RearTrainFrontPos;
5996 int FrontTrainRearPos, FrontTrainFrontPos, FrontTrainExitPos;
5999 if(LocationName ==
"")
6001 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6005 bool TemporaryDelay =
false;
6007 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
6031 AnsiString SplittingTrainDescription =
Description;
6038 for(
int x = 0; x < 4; x++)
6058 double NewTrainPowerAtRail;
6064 NewTrainMass =
Mass * double(MassPercent)/100.0;
6066 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6067 if(NewTrainPowerAtRail == 0)
6069 NewTrainPowerAtRail = 0.08;
6077 NewTrainMass =
Mass;
6105 if(!SplitTrainExplicitDescription)
6196 TTrain *TrainToBeJoinedBy;
6229 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6231 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6295 int RouteNumber = -1;
6300 int CorrectRouteID = OR.
RouteID;
6306 bool FirstPass =
true;
6311 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6445 for(
int x = 0; x < IncNum; x++)
6478 else if(Ptr->
Command ==
"jbo")
6483 else if(Ptr->
Command ==
"dsc")
6494 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6500 bool IncludeFER =
false;
6508 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6513 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6524 else if(Ptr->
Command ==
"Fjo")
6530 else if(Ptr->
Command ==
"Frh")
6540 else if(Ptr->
Command ==
"Frh-sh")
6591 else if(Ptr->
Command ==
"jbo")
6596 else if(Ptr->
Command ==
"dsc")
6601 else if(Ptr->
Command ==
"cdt")
6609 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7031 int RouteNumber = -1;
7036 int CorrectRouteID = OR.
RouteID;
7042 bool FirstPass =
true;
7047 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7075 ",FloatingLabelNextString" +
"," +
HeadCode);
7076 AnsiString RetStr =
"", LocationName =
"";
7079 if(ActionTime == TDateTime(-1))
7083 if(ActionTime == TDateTime(-1))
7089 if(ActionTime != TDateTime(-1))
7097 throw Exception(
"Error - start entry in FloatingLabelNextString");
7141 else if(Ptr->
Command ==
"Fns")
7147 else if(Ptr->
Command ==
"F-nshs")
7178 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7180 else if(Ptr->
Command ==
"Frh")
7182 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7184 else if(Ptr->
Command ==
"Fer")
7186 AnsiString AllowedExits =
"";
7189 else if(Ptr->
Command ==
"Fjo")
7194 else if(Ptr->
Command ==
"jbo")
7199 else if(Ptr->
Command ==
"fsp")
7204 else if(Ptr->
Command ==
"rsp")
7209 else if(Ptr->
Command ==
"cdt")
7213 else if(Ptr->
Command ==
"dsc")
7222 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7266 else if(Ptr->
Command ==
"Fns")
7272 else if(Ptr->
Command ==
"F-nshs")
7303 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7305 else if(Ptr->
Command ==
"Frh")
7307 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7309 else if(Ptr->
Command ==
"Fer")
7311 AnsiString AllowedExits =
"";
7314 else if(Ptr->
Command ==
"Fjo")
7319 else if(Ptr->
Command ==
"jbo")
7324 else if(Ptr->
Command ==
"fsp")
7329 else if(Ptr->
Command ==
"rsp")
7334 else if(Ptr->
Command ==
"cdt")
7338 else if(Ptr->
Command ==
"dsc")
7347 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7391 else if(Ptr->
Command ==
"Fns")
7397 else if(Ptr->
Command ==
"F-nshs")
7428 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7430 else if(Ptr->
Command ==
"Frh")
7432 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7434 else if(Ptr->
Command ==
"Fer")
7436 AnsiString AllowedExits =
"";
7439 else if(Ptr->
Command ==
"Fjo")
7444 else if(Ptr->
Command ==
"jbo")
7449 else if(Ptr->
Command ==
"fsp")
7454 else if(Ptr->
Command ==
"rsp")
7459 else if(Ptr->
Command ==
"cdt")
7463 else if(Ptr->
Command ==
"dsc")
7607 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7608 AnsiString DepTime =
"", EventTime =
"";
7609 bool CDTFlag =
false;
7611 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7612 AnsiString TowardsLocation =
"";
7615 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7617 TowardsLocation = AVI->LocationName;
7619 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7628 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7635 if(AVI->Command ==
"cdt")
7640 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7655 RetStr +=
"\nNew service splits at approx. " + EventTime;
7659 if(AVI->Command ==
"jbo")
7678 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
7693 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
7697 if(AVI->Command ==
"Fjo")
7716 if(AVI->Command ==
"Frh")
7718 RetStr +=
"\nNew service finishes and remains at the location.";
7722 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7729 if(TowardsLocation !=
"")
7731 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7735 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7740 if(TowardsLocation !=
"")
7742 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7746 RetStr +=
"\nNew service departs at " + DepTime;
7755 if(TowardsLocation !=
"")
7757 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7761 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7766 if(TowardsLocation !=
"")
7768 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7772 RetStr +=
"\nNew service departs at approx. " + DepTime;
7789 if(TowardsLocation !=
"")
7791 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7795 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7800 if(TowardsLocation !=
"")
7802 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7806 RetStr +=
"\nNew service departs at approx. " + DepTime;
7825 ",FloatingTimetableString" +
"," +
HeadCode);
7826 AnsiString RetStr =
"", PartStr =
"";
7828 bool SkipDep =
false, SkipDepActedOn =
false;
7834 throw Exception(
"Error - start entry in FloatingTimetableString");
7837 bool FirstPass =
true;
7844 AnsiString TrainLoc =
"";
7897 AnsiString TrainLoc =
"";
7938 else if(Ptr->
Command ==
"Fns")
7944 else if(Ptr->
Command ==
"F-nshs")
7977 else if(Ptr->
Command ==
"Frh")
7981 else if(Ptr->
Command ==
"Fer")
7983 AnsiString AllowedExits =
"";
7986 else if(Ptr->
Command ==
"Fjo")
7991 else if(Ptr->
Command ==
"jbo")
7996 else if(Ptr->
Command ==
"fsp")
8006 PartStr+=
", split mass%-Power% = 50-50";
8009 else if(Ptr->
Command ==
"rsp")
8019 PartStr+=
", split mass%-Power% = 50-50";
8022 else if(Ptr->
Command ==
"cdt")
8026 else if(Ptr->
Command ==
"dsc")
8032 RetStr = RetStr +
'\n' + PartStr;
8046 SkipDepActedOn =
true;
8057 RetStr =
"Timetable finished";
8061 RetStr =
"No timetable";
8065 return(
"Timetable:\n" + RetStr);
8218 bool ForwardHeadCode;
8222 ForwardHeadCode =
true;
8227 ForwardHeadCode =
false;
8370 if(ColourNumber == 0)
8374 else if(ColourNumber == 1)
8378 else if(ColourNumber == 2)
8382 else if(ColourNumber == 3)
8386 else if(ColourNumber == 4)
8390 else if(ColourNumber == 5)
8394 else if(ColourNumber == 6)
8398 else if(ColourNumber == 7)
8402 else if(ColourNumber == 8)
8406 else if(ColourNumber == 9)
8410 else if(ColourNumber == 10)
8414 else if(ColourNumber == 11)
8418 else if(ColourNumber == 12)
8422 else if(ColourNumber == 13)
8426 else if(ColourNumber == 14)
8438 for(
int x = 0; x < 4; x++)
8445 for(
int x = 0; x < 4; x++)
8530 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8533 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8534 bool GiveMessagesFalse =
false;
8535 bool CheckLocationsExistInRailwayTrue =
true;
8542 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8545 if(Marker[6] ==
'1')
9010 bool HideFlashingTrain =
true;
9013 Graphics::TBitmap *SmallTrainBitmap;
9054 HideFlashingTrain =
false;
9059 HideFlashingTrain =
false;
9064 HideFlashingTrain =
false;
9069 HideFlashingTrain =
false;
9074 HideFlashingTrain =
false;
9078 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9082 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9106 for(
int y = 0; y < 3; y++)
9110 bool FoundFlag =
false;
9121 if(IMPair.first != IMPair.second)
9148 if((LocationName ==
"") && (
MidElement > -1))
9152 if((LocationName ==
"") && (
LagElement > -1))
9156 if(LocationName ==
"")
9158 throw Exception(
"Error - Location name not set in TrainAtLocation");
9169 for(
int x = 0; x < 4; x++)
9181 for(
int x = 0; x < 4; x++)
9198 AnsiString(LinkNumber) +
"," +
HeadCode);
9250 int DistanceToRedSignal = 0, DistanceToExit = -1;
9251 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9255 float MinsEarly = 0;
9256 TDateTime DepartureTime;
9257 TDateTime ArrivalTime;
9285 if(TempTTE < LastTimeToExit)
9320 if(TempTTE < LastTimeToExit)
9343 if(TempTTE < LastTimeToExit)
9373 if(TempTTE < LastTimeToExit)
9396 if(TempTTE < LastTimeToExit)
9439 float CurrentStopTime;
9440 float LaterStopTime;
9441 float RecoverableTime;
9449 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9456 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9457 bool DistanceToExitSet = (DistanceToExit > -1);
9458 int GenericDistance = DistanceToRedSignal;
9459 if(DistanceToExitSet)
9461 GenericDistance = DistanceToExit;
9477 float TimeToSubtract, TotalStopTime;
9480 TimeToSubtract = RecoverableTime;
9523 if(CurrentStopTime > 0)
9525 TotalStopTime = CurrentStopTime + LaterStopTime;
9534 else if((MinsEarly > 0) && !
Stopped())
9536 TotalStopTime = LaterStopTime + MinsEarly;
9540 if(LaterStopTime == 0)
9542 TotalStopTime = CurrentStopTime;
9548 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9551 if(AvTrackSpeed < 30)
9555 int Speed = AvTrackSpeed;
9565 if(DistanceToRedSignalSet)
9567 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9577 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9606 if((NextEntryPos == 0) || (NextEntryPos == 2))
9733 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9775 int IncrementalMinutes = 0;
9776 int IncrementalDigits = 0;
9784 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
9820 if(AVEntry0.
Command ==
"Snt-sh")
9825 int IncrementalMinutes = 0;
9826 int IncrementalDigits = 0;
9834 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
9878 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9958 AnsiString Loc =
"";
9959 bool ElementFound =
false;
9964 ElementFound =
true;
9969 ElementFound =
true;
9974 ElementFound =
true;
10003 else if(AVEntryPtr->
Command ==
"Fer")
10005 bool CorrectExit =
false;
10012 CorrectExit =
true;
10117 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10135 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10150 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10161 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10162 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10163 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10165 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10166 "," + AnsiString(Mass) +
"," + ModeStr);
10168 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10170 int RearExitPos = -1;
10172 for(
int x = 0; x < 4; x++)
10179 if(RearExitPos == -1)
10181 throw Exception(
"Error, RearExit == -1 in AddTrain");
10183 bool ReportFlag =
true;
10188 ReportFlag =
false;
10200 if(ModeStr ==
"Timetable")
10206 if(MaxRunningSpeed < 10)
10208 MaxRunningSpeed = 10;
10210 if(SignallerSpeed < 10)
10212 SignallerSpeed = 10;
10214 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10215 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10222 if(SignallerControl)
10252 if(!SignallerControl)
10267 if(!SignallerControl)
10278 AnsiString Loc =
"";
10295 if(!SignallerControl)
10314 int RouteNumber = -1;
10315 bool SignalsSet =
false;
10322 int RouteStartPosition;
10326 if(FirstPair.first == RouteNumber)
10328 RouteStartPosition = FirstPair.second;
10330 else if(SecondPair.first == RouteNumber)
10332 RouteStartPosition = SecondPair.second;
10336 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10342 else if(RouteNumber > -1)
10362 int LinkedRouteNumber = -1;
10383 int RouteStartPosition;
10387 if(FirstPair.first == RouteNumber)
10389 RouteStartPosition = FirstPair.second;
10391 else if(SecondPair.first == RouteNumber)
10393 RouteStartPosition = SecondPair.second;
10397 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10403 else if(RouteNumber > -1)
10423 int LinkedRouteNumber = -1;
10444 AnsiString(TrackVectorNumber));
10447 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10456 throw Exception(
"Error, VecPos not set in EntryPos");
10458 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10463 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10468 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10482 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10490 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10500 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10521 return(RepeatTime);
10530 AnsiString RetStr =
"", PartStr =
"";
10538 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10546 if(Ptr->SignallerControl)
10548 RetStr =
"Train under signaller control";
10553 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10564 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10568 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10572 else if(Ptr->FormatType ==
PassTime)
10576 else if(Ptr->Command ==
"Fns")
10582 else if(Ptr->Command ==
"F-nshs")
10585 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10592 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10599 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10602 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10605 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10612 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10614 PartStr =
"Terminate at " + Ptr->LocationName;
10616 else if(Ptr->Command ==
"Frh")
10618 PartStr =
"Terminate at " + Ptr->LocationName;
10620 else if(Ptr->Command ==
"Fer")
10622 AnsiString AllowedExits;
10626 else if(Ptr->Command ==
"Fjo")
10629 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10631 else if(Ptr->Command ==
"jbo")
10634 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10636 else if(Ptr->Command ==
"fsp")
10641 else if(Ptr->Command ==
"rsp")
10646 else if(Ptr->Command ==
"cdt")
10650 else if(Ptr->Command ==
"dsc")
10656 RetStr = RetStr +
'\n' + PartStr;
10664 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10675 TTrainDataEntry *LinkedTrainDataPtr,
int IncrementalMinutes,
int IncrementalDigits, AnsiString RetStr)
10678 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10679 AnsiString DepTime =
"", EventTime =
"";
10680 bool CDTFlag =
false;
10682 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10683 AnsiString TowardsLocation =
"";
10686 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10688 TowardsLocation = AVI->LocationName;
10690 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10699 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10705 if(AVI->Command ==
"cdt")
10707 CDTFlag = !CDTFlag;
10710 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10713 RetStr +=
"\nNew service splits at " + EventTime;
10717 if(AVI->Command ==
"jbo")
10720 RetStr +=
"\nNew service joined by " +
GetRepeatHeadCode(70, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
10724 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
10727 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
10731 if(AVI->Command ==
"Fjo")
10734 RetStr +=
"\nNew service finishes and joins " +
TrainController->
GetRepeatHeadCode(71, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
10738 if(AVI->Command ==
"Frh")
10740 RetStr +=
"\nNew service finishes and remains at location.";
10744 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10749 if(TowardsLocation !=
"")
10751 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10755 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10760 if(TowardsLocation !=
"")
10762 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10766 RetStr +=
"\nNew service departs at " + DepTime;
10931 ActiveTrackElementNameMapEntry.second = 0;
10937 std::ifstream TTBLFile(FileName, std::ios_base::binary);
10940 if(TTBLFile.is_open())
10942 char *TrainTimetableString =
new char[10000];
10944 bool EndOfFile =
false;
10947 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10949 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10956 delete[] TrainTimetableString;
10960 AnsiString OneLine(TrainTimetableString);
10961 bool FinalCallFalse =
false;
10962 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10966 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10967 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10972 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
10974 delete[] TrainTimetableString;
10978 OneLine = AnsiString(TrainTimetableString);
10984 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10986 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10996 OneLine = AnsiString(TrainTimetableString);
10998 if(OneLine.Length() > 9999)
11000 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
11002 delete[] TrainTimetableString;
11006 bool FinalCallFalse =
false;
11007 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11011 delete[] TrainTimetableString;
11015 if(EndOfFile && (Count < 2))
11018 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
11020 delete[] TrainTimetableString;
11026 delete[] TrainTimetableString;
11031 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11042 bool CheckLocationsExistInRailway)
11170 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11180 if(OneLine[1] !=
'*')
11182 int SCPos = OneLine.Pos(
';');
11193 bool AllCommas =
true;
11195 for(
int x = 1; x < OneLine.Length() + 1; x++)
11197 if(OneLine[x] !=
',')
11202 if(AllCommas || (OneLine ==
""))
11217 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11218 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11219 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11220 TDateTime StartTime(0);
11222 bool Warning =
false;
11249 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11250 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11251 double MaxBrakeRate = 0;
11252 double PowerAtRail = 0;
11253 int SignallerSpeed = 0;
11254 if(OneLine[1] ==
'*')
11260 int Pos = OneLine.Pos(
',');
11263 int SubStringLength = 20;
11264 if(OneLine.Length() < 20)
11266 SubStringLength = OneLine.Length();
11268 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11272 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11273 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11284 TempTrainDataEntry.
HeadCode = HeadCode;
11288 if(Description !=
"")
11293 TempTrainDataEntry.
Mass = Mass;
11301 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11304 while(NewRemainder[NewRemainder.Length()] ==
',')
11306 if(NewRemainder.Length() > 1)
11308 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11317 if(NewRemainder ==
"")
11319 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11324 int CommaCount = 0;
11325 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11327 if(NewRemainder[x] ==
',')
11332 if(CommaCount == 0)
11334 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11336 int SubStringLength = 20;
11337 if(OneLine.Length() < 20)
11339 SubStringLength = OneLine.Length();
11342 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11343 OneLine.SubString(1, SubStringLength) +
"'....");
11348 AnsiString OneEntry =
"";
11353 bool FinishFlag =
false;
11355 for(
int x = 0; x < CommaCount + 1; x++)
11357 if((CommaCount == 0) || (x < CommaCount))
11362 if(CommaCount == 0)
11364 OneEntry = NewRemainder;
11369 Pos = NewRemainder.Pos(
',');
11370 OneEntry = NewRemainder.SubString(1, Pos - 1);
11371 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11377 RearStartOrRepeatMins = 0;
11378 FrontStartOrRepeatDigits = 0;
11379 NumberOfRepeats = 0;
11380 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11381 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11383 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11394 if(Warning && (Second ==
"Frh"))
11396 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11400 if(Warning && (Second ==
"Fjo"))
11403 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11440 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11444 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11446 if(NewRemainder[1] !=
'R')
11449 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11455 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11459 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11462 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11468 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11473 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11478 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11481 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11497 TDateTime TempTime;
11503 ActionVectorEntry.
Warning = Warning;
11519 ActionVectorEntry.
Command = Second;
11534 else if(FormatType ==
TimeCmd)
11540 ActionVectorEntry.
Command = Second;
11548 ActionVectorEntry.
Command = Second;
11549 ActionVectorEntry.
ExitList = ExitList;
11557 ActionVectorEntry.
Command = Second;
11571 ActionVectorEntry.
Command = Second;
11582 ActionVectorEntry.
Command = Second;
11592 ActionVectorEntry.
Command = Second;
11594 if((Second ==
"fsp") || (Second ==
"rsp"))
11609 ActionVectorEntry.
Command = Second;
11618 ActionVectorEntry.
Command = Second;
11624 ActionVectorEntry.
Command = Second;
11632 ActionVectorEntry.
Command = Second;
11635 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11640 OneEntry = NewRemainder;
11645 RearStartOrRepeatMins = 0;
11646 FrontStartOrRepeatDigits = 0;
11647 NumberOfRepeats = 0;
11648 if((FinishFlag) && (OneEntry[1] !=
'R'))
11651 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11655 if(OneEntry[1] !=
'R')
11657 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11658 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11660 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'.\nIf the program version is not the latest the "
11661 "timetable may have features that aren't compatible with the version in use.");
11678 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11685 TDateTime TempTime;
11691 ActionVectorEntry.
Warning = Warning;
11698 ActionVectorEntry.
Command = Second;
11706 ActionVectorEntry.
Command = Second;
11715 ActionVectorEntry.
Command = Second;
11724 ActionVectorEntry.
Command = Second;
11734 ActionVectorEntry.
Command = Second;
11735 ActionVectorEntry.
ExitList = ExitList;
11739 ActionVectorEntry.
Command = Second;
11741 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11746 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11762 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11781 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11786 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
11801 if(TimeStr.Length() < 5)
11806 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
11811 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
11816 if(TimeStr[3] !=
':')
11821 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
11826 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
11831 while(TimeStr.Length() > 5)
11833 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
11835 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
11836 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
11838 if((WholeHours + FracHour) >= 95.98334)
11843 Time = TDateTime((WholeHours + FracHour) / 24);
11850 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
11851 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
11860 TDateTime TempTime;
11862 if(OneEntry.Length() > 0)
11864 if(OneEntry[1] ==
'W')
11867 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
11871 if(OneEntry ==
"Frh")
11881 if(OneEntry.Length() < 7)
11886 int Pos = OneEntry.Pos(
';');
11894 First = OneEntry.SubString(1, 5);
11900 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
11903 if((Remainder.Length() >= 3) && (Remainder[1] >=
'0') && (Remainder[1] <=
'9') && (Remainder[2] >=
'0') && (Remainder[2] <=
'9') && (Remainder[3] ==
':'))
11906 if(Remainder.Length() < 7)
11911 Pos = Remainder.Pos(
';');
11918 Second = Remainder.SubString(1, 5);
11924 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11937 Pos = Remainder.Pos(
';');
11940 Second = Remainder;
11941 if(Second ==
"cdt")
11966 if((Pos != 4) && (Pos != 7) && (Pos != 8))
11972 Second = Remainder.SubString(1, Pos - 1);
11974 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11976 Pos = Remainder.Pos(
';');
11983 Third = Remainder.SubString(1, Pos - 1);
11984 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11987 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11990 int SpacePos = Third.Pos(
' ');
11996 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
11997 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
11999 if(CheckLocationsExistInRailway)
12009 if(Second ==
"Snt")
12032 if(Second ==
"Sns-sh")
12051 if(Second ==
"F-nshs")
12065 if(Second ==
"Sns-fsh")
12079 if(Second ==
"Fns-sh")
12099 if(Second ==
"pas")
12114 if(Second ==
"Fer")
12121 if(CheckLocationsExistInRailway)
12132 if(Second ==
"dsc")
12134 if(Third.Length() > 60)
12136 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12140 for(
int x = 1; x < Third.Length() + 1; x++)
12143 if((Third[x] <
' ') && (Third[x] >= 0))
12145 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12161 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12162 (Second !=
"Frh-sh"))
12174 if(Second ==
"Frh-sh")
12182 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12186 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12190 if((Second ==
"Sfs") || (Second ==
"Sns"))
12195 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12212 bool ErrorFlag =
false;
12214 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
12218 int pos = SplitDistributionString.Pos(
'-');
12225 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
12226 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
12229 int x = MassStr.ToInt();
12230 int y = PowerStr.ToInt();
12231 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
12236 catch(
const Exception &e)
12243 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
12244 "power for the new split-off train");
12265 if((LocStr.Length() >= 3) && (LocStr[1] >=
'0') && (LocStr[1] <=
'9') && (LocStr[2] >=
'0') && (LocStr[2] <=
'9') && (LocStr[3] ==
':'))
12270 for(
int x = 1; x < LocStr.Length() + 1; x++)
12272 if(((LocStr[x] <
' ') && (LocStr[x] >= 0)) || (LocStr[x] ==
',') || (LocStr[x] ==
';'))
12286 if(CheckLocationsExistInRailway)
12291 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
12292 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
12293 "that includes a continuation will not be valid.");
12311 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
12314 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
12319 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
12321 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
12323 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
12329 for(
int x = 3; x >= 0; x--)
12331 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
12332 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
12334 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
12350 AnsiString CurrentID =
"";
12352 if(IDSet.Length() == 0)
12354 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
12358 for(
int x = 1; x <= IDSet.Length(); x++)
12361 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
12363 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
12385 int Pos = IDSet.Pos(
' ');
12396 CurrentID = IDSet.SubString(1, Pos - 1);
12397 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12409 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12416 if(!ExitList.empty())
12418 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12420 if(*ELIT == VecPos)
12422 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12429 ExitList.push_back(VecPos);
12439 Pos = IDSet.Pos(
' ');
12446 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12453 AnsiString Remainder =
"";
12454 int SemiColonCount = 0;
12456 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12458 if(TrainInfoStr[x] ==
';')
12463 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12465 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12466 "'. Should be headcode + optional description for a continuing service;" +
12467 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12471 if(SemiColonCount == 0)
12473 HeadCode = TrainInfoStr;
12482 if(SemiColonCount == 1)
12484 Pos = TrainInfoStr.Pos(
';');
12485 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12486 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12492 if(Description ==
"")
12494 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12498 if(Description.Length() > 60)
12500 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12504 for(
int x = 1; x < Description.Length() + 1; x++)
12507 if((Description[x] <
' ') && (Description[x] >= 0))
12509 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12518 Pos = TrainInfoStr.Pos(
';');
12519 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12520 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12526 Pos = Remainder.Pos(
';');
12527 Description = Remainder.SubString(1, Pos - 1);
12528 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12529 if(Description ==
"")
12531 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12535 if(Description.Length() > 60)
12537 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12541 for(
int x = 1; x < Description.Length() + 1; x++)
12544 if((Description[x] <
' ') && (Description[x] >= 0))
12546 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12551 Pos = Remainder.Pos(
';');
12552 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
12554 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12555 if(StartSpeedStr ==
"")
12557 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
12561 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
12563 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
12565 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
12570 StartSpeed = StartSpeedStr.ToInt();
12576 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12580 Pos = Remainder.Pos(
';');
12581 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
12583 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12584 if(MaxRunningSpeedStr ==
"")
12586 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
12590 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
12592 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
12594 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
12599 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
12605 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12609 if(MaxRunningSpeed < 10)
12612 MaxRunningSpeed = 10;
12615 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12619 Pos = Remainder.Pos(
';');
12620 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
12622 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12625 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
12629 for(
int x = 1; x < MassStr.Length() + 1; x++)
12631 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
12633 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
12638 Mass = MassStr.ToInt() * 1000;
12644 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
12650 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
12654 Pos = Remainder.Pos(
';');
12655 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
12657 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12658 if(MaxBrakeForceStr ==
"")
12660 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
12664 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
12666 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
12668 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
12673 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
12676 if((MaxBrakeForce / Mass) > 1)
12678 MaxBrakeForce = Mass;
12681 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
12685 if((MaxBrakeForce / Mass) < 0.01)
12687 MaxBrakeForce = Mass * 0.01;
12690 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
12695 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
12697 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
12699 if(SemiColonCount == 6)
12701 GrossPowerStr = Remainder;
12702 SignallerSpeedStr =
"30";
12706 Pos = Remainder.Pos(
';');
12707 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12708 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12711 if(GrossPowerStr ==
"")
12713 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12717 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12719 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12721 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12727 double GrossPower = GrossPowerStr.ToInt() * 1000;
12734 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12738 else if(GrossPower == 0)
12743 else if((GrossPower > 0) && (GrossPower < 10000))
12746 GrossPower = 10000;
12748 PowerAtRail = GrossPower * 0.8;
12752 if(SignallerSpeedStr ==
"")
12754 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12758 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12760 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12762 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12767 SignallerSpeed = SignallerSpeedStr.ToInt();
12773 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12777 if(SignallerSpeed < 10)
12780 SignallerSpeed = 10;
12783 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12801 if(OneEntry.Length() < 7)
12803 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12807 int SemiColonCount = 0;
12809 for(
int x = 1; x < OneEntry.Length() + 1; x++)
12811 if(OneEntry[x] ==
';')
12816 if(SemiColonCount != 3)
12818 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12822 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
12824 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12828 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
12833 Pos = Remainder.Pos(
';');
12834 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
12836 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12837 if(MinutesStr ==
"")
12839 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
12843 if(MinutesStr.Length() > 3)
12846 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
12850 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
12852 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
12854 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
12859 RearStartOrRepeatMins = MinutesStr.ToInt();
12860 if(RearStartOrRepeatMins == 0)
12862 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
12866 Pos = Remainder.Pos(
';');
12867 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
12869 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12870 if(DigitsStr ==
"")
12872 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
12876 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
12878 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
12880 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
12885 if(DigitsStr.Length() > 2)
12887 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
12891 FrontStartOrRepeatDigits = DigitsStr.ToInt();
12905 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
12909 AnsiString NumberStr = Remainder;
12911 if(NumberStr ==
"")
12913 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
12917 if(NumberStr.Length() > 4)
12920 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
12924 for(
int x = 1; x < NumberStr.Length() + 1; x++)
12926 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
12929 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
12934 NumberOfRepeats = NumberStr.ToInt();
12935 if(NumberOfRepeats == 0)
12937 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
13211 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
13232 TwoLocationFlag =
false;
13238 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
13252 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
13268 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
13280 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
13306 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
13319 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after "
13320 "an 'Sns' or 'Sfs' event for: " + TDEntry.
HeadCode +
". The program is unable to determine the "
13321 "location of any other type of finish.");
13327 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13333 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' "
13334 "event for: " + TDEntry.
HeadCode);
13344 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13349 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
13359 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13364 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
13374 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13385 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
13395 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
13407 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13414 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
13423 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
13442 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
13444 AnsiString LocationName =
"";
13458 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
13459 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13468 if(AVEntry0.
Command ==
"Snt-sh")
13482 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
13498 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' followed by an illegal event for: " +
13499 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13511 bool FoundFlag =
false;
13515 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13517 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13529 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13542 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13567 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13589 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13611 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13636 bool LocFoundFlag, FnsFoundFlag;
13640 LocFoundFlag =
false;
13641 FnsFoundFlag =
false;
13642 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
13647 FnsFoundFlag =
true;
13656 LocFoundFlag =
true;
13667 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
13668 "by an event at the same location that has an identified location name, normally an arrival, see "
13675 if(FnsFoundFlag && !LocFoundFlag)
13677 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
13678 "by an event at the same location that has an identified location name, normally an arrival, see "
13692 if(AVEntry0.
Command ==
"Sns")
13704 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sns' event for: " + TDEntry.
HeadCode);
13712 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13713 ". The event isn't valid for a stationary train.");
13721 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13728 TDateTime SnsEventTime = AVEntry0.
EventTime;
13731 bool BreakFlag =
false;
13734 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13739 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
13761 if(AVEntry0.
Command ==
"Sfs")
13763 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13771 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
13783 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13788 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13808 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13815 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13830 if(AVEntry0.
Command ==
"Sfs")
13842 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
13850 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13851 ". The event isn't valid for a stationary train.");
13859 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13866 TDateTime SfsEventTime = AVEntry0.
EventTime;
13868 bool BreakFlag =
false;
13871 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13876 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
13896 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13901 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13922 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13929 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13934 else if((AVEntry.
Command ==
"Sns") || (AVEntry.
Command ==
"Sfs"))
13937 "Please make sure that the finish event of the service that links to this event is preceded by an "
13938 "event at the same location that has an identified location name, normally an arrival.");
13943 else if(AVEntry.
Command ==
"Snt-sh")
13946 "Please make sure that the service starts with zero speed and is at a named location.");
13951 else if((AVEntry.
Command ==
"Sns-fsh") || (AVEntry.
Command ==
"Sns-sh"))
13954 "Please make sure that the event is followed (not necessarily immediately) by a departure.");
13961 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13974 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13984 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish event for: " + TDEntry.
HeadCode);
13991 if(AVEntry.
Command ==
"F-nshs")
13996 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
14024 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
14025 ". The event isn't valid for a stationary train.");
14035 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
14043 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
14044 ". The event isn't valid for a stationary train.");
14062 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
14063 ". The event isn't valid for a stationary train.");
14081 SecondPassMessage(GiveMessages,
"Error in timetable - a 'dsc' is followed by an illegal event for: " + TDEntry.
HeadCode +
14082 ". The event isn't valid for a stationary train.");
14092 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
14100 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
14101 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
14119 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
14120 ". The event isn't valid for a moving train.");
14142 bool LastEntryIsAnArrival =
false;
14149 LastEntryIsAnArrival =
false;
14150 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14157 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14159 if(LastEntryIsAnArrival)
14163 LastEntryIsAnArrival =
false;
14169 LastEntryIsAnArrival =
true;
14176 LastEntryIsAnArrival =
true;
14177 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14184 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14186 if(LastEntryIsAnArrival)
14190 LastEntryIsAnArrival =
false;
14196 LastEntryIsAnArrival =
true;
14206 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14214 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
14222 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
14223 ". The event isn't valid for a stationary train.");
14234 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
14242 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
14243 ". The event isn't valid for a moving train.");
14257 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14264 throw Exception(
"Timetable error, TimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14268 throw Exception(
"Timetable error, TimeLoc event has neither arrival nor departure time set for " + TDEntry.
HeadCode);
14275 throw Exception(
"Timetable error, TimeTimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14279 throw Exception(
"Timetable error, TimeTimeLoc event has either arrival or departure time not set for " + TDEntry.
HeadCode);
14288 throw Exception(
"Timetable error, Cmd or PassTime event has EventTime not set for " + TDEntry.
HeadCode);
14292 throw Exception(
"Timetable error, Cmd or PassTime event has either arrival or departure time set for " + TDEntry.
HeadCode);
14299 throw Exception(
"Timetable error, Repeat event has a time set for " + TDEntry.
HeadCode);
14310 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14325 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
14333 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
14348 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14360 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14372 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
14373 ", may be before timetable start time");
14384 AnsiString LastLocationName =
"";
14388 bool LastEntryIsAnArrival =
false;
14393 LastEntryIsAnArrival =
false;
14394 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14395 if(LastLocationName !=
"")
14397 throw Exception(
"Timetable error, moving Snt event has LocationName set for " + TDEntry.
HeadCode);
14399 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
14412 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14424 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14437 TwoLocationFlag =
true;
14442 LastEntryIsAnArrival =
false;
14446 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14449 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14454 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
14457 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
14463 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14469 LastEntryIsAnArrival =
true;
14470 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14471 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14483 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14495 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14508 TwoLocationFlag =
true;
14513 LastEntryIsAnArrival =
false;
14517 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14520 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14528 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
14535 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14543 AnsiString LocationNameToBeChecked =
"";
14548 unsigned int y = 0;
14562 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
14563 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
14581 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
14590 TwoLocationFlag =
true;
14601 if(TwoLocationFlag)
14611 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14616 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat event doesn't have a location name set for " + TDEntry.
HeadCode);
14618 AnsiString LocName =
"";
14624 throw Exception(
"Error, 'Snt' event at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
14631 throw Exception(
"Error, 'Snt' unlocated event has a location name set for " + TDEntry.
HeadCode);
14654 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14679 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14701 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14723 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14742 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14745 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
14760 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14765 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
14769 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
14773 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
14777 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
14816 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14818 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
14824 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
14837 int IncMinutes = 0;
14847 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14853 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
14859 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
14864 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14870 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
14875 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14888 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14914 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
14922 if(HeadCode.Length() > 4)
14924 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
14935 int ForwardCount = 0;
14936 int ReverseCount = 0;
14938 if(MainHeadCode == SecondHeadCode)
14940 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
14949 if(TDEntry.
HeadCode == MainHeadCode)
14951 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14966 if(ForwardCount == 0)
14969 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
14971 if(ForwardCount > 2)
14974 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
14975 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14984 if(TDEntry.
HeadCode == SecondHeadCode)
14986 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15001 if(ReverseCount == 0)
15003 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
15008 if(ReverseCount > 2)
15011 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
15012 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15017 if(ForwardCount != ReverseCount)
15019 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
15020 " than the other way round");
15051 int ForwardCount = 0;
15052 int ReverseCount = 0;
15053 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15062 if(TDEntry.
HeadCode == MainHeadCode)
15064 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15067 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15072 ForwardEntryPtr = &AVEntry;
15074 ForwardTDVectorNumber = x;
15077 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
15078 (AVEntry.
Command ==
"Frh-sh")))
15083 ForwardEntryPtr = &AVEntry;
15085 ForwardTDVectorNumber = x;
15091 if(ForwardCount == 0)
15094 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
15096 if(ForwardCount > 1)
15098 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
15108 if(TDEntry.
HeadCode == OtherHeadCode)
15110 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15113 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15119 ReverseEntryPtr = &AVEntry;
15120 ReverseTDVectorNumber = x;
15123 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
15129 ReverseEntryPtr = &AVEntry;
15130 ReverseTDVectorNumber = x;
15137 if(ReverseCount == 0)
15139 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
15144 if(ReverseCount > 1)
15146 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15153 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
15154 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
15155 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
15156 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
15160 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
15167 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
15172 if(SetDataAndCheckLocations)
15174 if(ForwardEntryPtr->LocationName ==
"")
15176 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15177 ". One or other service does not have a location set");
15184 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15185 ". One or other service does not have a location set");
15190 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15192 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15193 " is at a different location to the referencing train " + MainHeadCode);
15202 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15204 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15205 " has a different event time to the referencing train " + MainHeadCode);
15213 if(ForwardShuttleStart && ReverseShuttleFinish)
15218 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
15219 " first repeat restart time not consistent with finish service " + OtherHeadCode);
15225 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
15228 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15230 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
15231 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15237 if(ReverseEntryPtr->
Command ==
"Fjo")
15240 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15242 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
15243 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15249 if(ReverseEntryPtr->
Command ==
"Fns")
15252 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15254 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
15255 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15261 if(ForwardEntryPtr->Command ==
"Sfs")
15263 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
15266 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
15273 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
15275 if(ReverseEntryPtr->
Command !=
"Sfs")
15277 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
15285 if(SetDataAndCheckLocations)
15289 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
15296 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
15302 bool StationLocation =
false;
15305 if(TEIt->LocationName == ForwardEntryPtr->LocationName)
15309 StationLocation =
true;
15313 if(StationLocation)
15317 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15327 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15333 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15345 if(ForwardEntryPtr->Command ==
"Sns")
15347 if(ReverseEntryPtr->
Command !=
"Fns")
15349 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
15350 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
15356 if(ForwardEntryPtr->Command ==
"Fns")
15358 if(ReverseEntryPtr->
Command !=
"Sns")
15360 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
15361 " and forms a new service with headcode " + OtherHeadCode);
15368 if(SetDataAndCheckLocations)
15370 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15382 if(ForwardEntryPtr->Command ==
"jbo")
15384 if(ReverseEntryPtr->
Command !=
"Fjo")
15386 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
15387 " and is joined by a train with headcode " + OtherHeadCode);
15393 if(ForwardEntryPtr->Command ==
"Fjo")
15395 if(ReverseEntryPtr->
Command !=
"jbo")
15397 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
15398 " and joins a train with headcode " + OtherHeadCode);
15405 if(SetDataAndCheckLocations)
15407 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15423 if(ForwardShuttleStart)
15426 if(!ReverseShuttleFinish)
15429 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
15430 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
15436 if(ReverseShuttleStart)
15439 if(!ForwardShuttleFinish)
15442 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
15443 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
15450 if(SetDataAndCheckLocations)
15452 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15465 bool MainRepeat =
false, OtherRepeat =
false;
15475 OtherRepeat =
true;
15478 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
15480 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
15481 " and the associated train with headcode " + OtherHeadCode);
15486 if(MainRepeat && OtherRepeat)
15492 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
15493 " and the associated train with headcode " + OtherHeadCode);
15515 while(Input[1] ==
' ')
15517 if(Input.Length() > 1)
15519 Input = Input.SubString(2, Input.Length() - 1);
15533 while(Input[Input.Length()] ==
' ')
15535 if(Input.Length() > 1)
15537 Input = Input.SubString(1, Input.Length() - 1);
15547 AnsiString Output =
"";
15548 bool DelimiterFound =
false;
15550 for(
int x = 1; x < Input.Length() + 1; x++)
15554 if(Input[x] ==
' ')
15559 if((Input[x] !=
',') && (Input[x] !=
';'))
15561 DelimiterFound =
false;
15562 Output = Output + Input[x];
15566 DelimiterFound =
true;
15567 Output = Output + Input[x];
15579 DelimiterFound =
false;
15580 for(
int x = Input.Length(); x > 0; x--)
15584 if(Input[x] ==
' ')
15589 if((Input[x] !=
',') && (Input[x] !=
';'))
15591 DelimiterFound =
false;
15592 Output = AnsiString(Input[x]) + Output;
15596 DelimiterFound =
true;
15597 Output = AnsiString(Input[x]) + Output;
15622 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
15624 throw Exception(
"Error, first event not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
15636 LocationName = LocRear;
15640 LocationName = LocFront;
15642 if(LocationName ==
"")
15663 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
15704 int RearPosition = 0, FrontPosition = 0;
15707 if(RearPosition < 0)
15714 if(FrontPosition < 0)
15726 for(
int x = 0; x < 4; x++)
15728 if(RearTrackElement.
Conn[x] == FrontPosition)
15743 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
15750 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
15756 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
15787 AnsiString(RearExitPos));
15798 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
15800 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
15803 AnsiString RearName, FrontName;
15819 FrontName = FrontTrackElement.
ElementID;
15822 int LockedVectorNumber;
15942 if(((RearTrackElement.
Attribute == 1) && (RearExitPos == 1)) || ((RearTrackElement.
Attribute == 0) && (RearExitPos == 3)))
15947 StopTTClockMessage(157, HeadCode +
" can't be created, points set wrongly at " + RearName);
15955 if(((FrontTrackElement.
Attribute == 1) && (FrontEntryPos == 1)) || ((FrontTrackElement.
Attribute == 0) && (FrontEntryPos == 3)))
15960 StopTTClockMessage(158, HeadCode +
" can't be created, points set wrongly at " + RearName);
15994 "," + AnsiString(IncDigits));
15997 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
16002 return(BaseHeadCode);
16004 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
16005 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
16007 while(NextRepeatDigits >= 100)
16009 NextRepeatDigits -= 100;
16011 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
16013 if(NextRepeatDigitsStr.Length() < 2)
16015 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
16017 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
16020 return(NextRepeatHeadCode);
16028 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
16029 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
16031 return(NextRepeatTime);
16040 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
16041 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16042 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16043 int RepeatSecs = RepeatMinutes * 60;
16045 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
16079 NonRepeatingHeadCode);
16080 int ForwardCount = 0;
16081 int ReverseCount = 0;
16082 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
16092 if(TDEntry.
HeadCode == MainHeadCode)
16094 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16100 ForwardEntryPtr = &AVEntry;
16102 ForwardTDVectorNumber = x;
16107 if(ForwardCount == 0)
16110 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
16112 if(ForwardCount > 1)
16114 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
16124 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
16126 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16133 ReverseEntryPtr = &AVEntry;
16134 ReverseTDVectorNumber = x;
16140 if(ReverseCount == 0)
16142 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
16147 if(ReverseCount > 1)
16149 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
16150 NonRepeatingHeadCode);
16155 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
16157 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
16162 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
16164 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
16169 if(SetDataAndCheckLocations)
16171 if(ForwardEntryPtr->LocationName ==
"")
16173 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16174 ". One or other service does not have a location set");
16181 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16182 ". One or other service does not have a location set");
16187 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
16189 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
16190 " is at a different location to the referencing train " + MainHeadCode);
16196 if(ForwardEntryPtr->Command ==
"F-nshs")
16199 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
16201 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
16202 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
16208 if(ForwardEntryPtr->Command ==
"Fns-sh")
16212 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
16214 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
16215 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
16221 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
16224 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16226 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
16227 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
16245 if(ForwardEntryPtr->Command ==
"Sns-sh")
16247 if(ReverseEntryPtr->
Command !=
"F-nshs")
16249 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
16250 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
16256 if(ForwardEntryPtr->Command ==
"F-nshs")
16258 if(ReverseEntryPtr->
Command !=
"Sns-sh")
16260 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
16261 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
16268 if(SetDataAndCheckLocations)
16270 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16282 if(ForwardEntryPtr->Command ==
"Sns-fsh")
16284 if(ReverseEntryPtr->
Command !=
"Fns-sh")
16287 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
16288 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
16294 if(ForwardEntryPtr->Command ==
"Fns-sh")
16296 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
16299 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
16300 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
16307 if(SetDataAndCheckLocations)
16309 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
16333 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
16334 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16335 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16336 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
16338 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
16362 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
16365 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
16366 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16368 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16370 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16375 while(LastActionCommand ==
"Fns")
16377 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
16378 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16379 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16382 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
16383 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16390 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
16393 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
16394 ". The linking of two or more shuttles is not permitted.");
16414 ShowMessage(
ServiceReference +
" (not a valid service ref.): " + Message);
16432 ShowMessage(Message);
16441 int Mins = Input, Hrs = 0;
16447 AnsiString AnsiMins = AnsiString(Mins);
16448 if(AnsiMins.Length() == 1)
16450 AnsiMins =
"0" + AnsiMins;
16452 AnsiString AnsiHrs = AnsiString(Hrs);
16453 if(AnsiHrs.Length() == 1)
16455 AnsiHrs =
"0" + AnsiHrs;
16458 return(AnsiHrs +
':' + AnsiMins);
16501 AnsiString(ActionEventType) +
"," + LocationID);
16502 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
16507 Prefix =
" ERROR: ";
16510 Prefix =
" HELD: ";
16511 ErrorLog =
" can't enter railway, train obstructing entry position ";
16512 WarningStr =
" can't enter railway, train obstructing entry position ";
16517 Prefix =
" HELD: ";
16518 ErrorLog =
" can't enter railway, route set against it at entry position ";
16519 WarningStr =
" can't enter railway, route set against it at entry position ";
16524 Prefix =
" HELD: ";
16525 ErrorLog =
" can't be created, train obstructing at ";
16526 WarningStr =
" can't be created, train obstructing at ";
16531 Prefix =
" HELD: ";
16532 ErrorLog =
" can't be created on a locked route at ";
16533 WarningStr =
" can't be created on a locked route at ";
16538 Prefix =
" HELD: ";
16539 ErrorLog =
" can't enter on a locked route at ";
16540 WarningStr =
" can't enter on a locked route at ";
16545 Prefix =
" HELD: ";
16546 ErrorLog =
" can't be created, points set wrongly at ";
16547 WarningStr =
" can't be created, points set wrongly at ";
16552 ErrorLog =
" left railway unexpectedly at ";
16557 ErrorLog =
" left railway at an incorrect exit at ";
16562 ErrorLog =
" failed to split - location too short at ";
16563 WarningStr =
" failed to split, location too short at ";
16568 Prefix =
" HELD: ";
16569 ErrorLog =
" unable to split - other train obstructing at ";
16570 WarningStr =
" unable to split - other train obstructing at ";
16575 ErrorLog =
" stopped at buffers unexpectedly at position ";
16579 ErrorLog =
" failed to stop at ";
16584 ErrorLog =
" failed to split at ";
16589 ErrorLog =
" failed to be joined by other train at ";
16594 ErrorLog =
" failed to change its description at ";
16599 ErrorLog =
" failed to join other train at ";
16604 ErrorLog =
" failed to terminate at ";
16609 ErrorLog =
" failed to form new service at ";
16614 ErrorLog =
" failed to exit railway ";
16619 ErrorLog =
" failed to change direction at ";
16624 ErrorLog =
" failed to pass ";
16629 ErrorLog =
" facing buffers and unable to start at ";
16633 ErrorLog =
" DERAILED at position ";
16634 Prefix =
" DERAILMENT: ";
16639 ErrorLog =
" CRASHED INTO BUFFERS at ";
16640 Prefix =
" CRASH: ";
16645 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
16646 Prefix =
" CRASH: ";
16651 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
16652 Prefix =
" CRASH: ";
16656 else if(ActionEventType ==
FailSPAD)
16658 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
16659 Prefix =
" SPAD: ";
16664 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
16665 Prefix =
" SPAD RISK: ";
16670 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
16674 Prefix =
" WARNING: ";
16675 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
16676 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
16681 Prefix =
" WARNING: ";
16682 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
16683 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
16688 Prefix =
" WARNING: ";
16689 ErrorLog =
" is without power so it can't depart from ";
16690 WarningStr =
" is without power so it can't depart from ";
16695 Prefix =
" WARNING: ";
16696 ErrorLog =
" can't depart because there is a train in front at ";
16697 WarningStr =
" can't depart because there is a train in front at ";
16735 std::ofstream OutFile(
"TrainData.csv");
16739 ShowMessage(
"Output file TrainData.csv failed to open");
16746 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
16751 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
16752 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
16753 "RepeatNumber" <<
'\n' <<
'\n';
16754 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16757 AnsiString TimetableEntryTypeStr;
16763 TimetableEntryTypeStr =
"NoFormat";
16769 TimetableEntryTypeStr =
"TimeLoc";
16775 TimetableEntryTypeStr =
"TimeTimeLoc";
16781 TimetableEntryTypeStr =
"TimeCmd";
16787 TimetableEntryTypeStr =
"StartNew";
16793 TimetableEntryTypeStr =
"TimeCmdHeadCode";
16799 TimetableEntryTypeStr =
"FinRemHere";
16805 TimetableEntryTypeStr =
"FNSShuttle";
16811 TimetableEntryTypeStr =
"SNTShuttle";
16817 TimetableEntryTypeStr =
"SNSShuttle";
16823 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
16829 TimetableEntryTypeStr =
"FSHNewService";
16835 TimetableEntryTypeStr =
"Repeat";
16841 TimetableEntryTypeStr =
"Default";
16852 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
16853 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16856 AnsiString RunningEntryStr;
16862 RunningEntryStr =
"NotStarted";
16868 RunningEntryStr =
"Running";
16874 RunningEntryStr =
"Exited";
16878 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
16895 ShowMessage(Message);
16896 BaseTime = TDateTime::CurrentDateTime();
16910 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16923 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16925 for(
int x = 0; x < NumberOfTrains; x++)
16927 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16947 int NumberOfTrains;
16954 for(
int x = 0; x < NumberOfTrains; x++)
16991 for(
int x = 0; x < LockedRouteVectorSize; x++)
16998 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
17009 int LockedRouteVectorSize;
17016 for(
int x = 0; x < LockedRouteVectorSize; x++)
17074 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17082 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
17093 int ContinuationAutoSigVectorSize;
17100 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17170 if(AVFirstEntry.
Command ==
"Snt")
17194 CTEMMP.second = CTEEntry;
17201 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
17209 CTEMMP.second = CTEEntry;
17230 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17247 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
17249 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
17260 AnsiString RetStr =
"", PartStr =
"";
17375 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17379 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17381 AnsiString ShortTTName =
"";
17383 for(
int x = TTFileName.Length(); x > 0; x--)
17385 if(TTFileName[x] ==
'\\')
17387 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
17392 ShowMessage(
"Creates two timetables named " + ShortTTName +
17393 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
17395 Screen->Cursor = TCursor(-11);
17397 AnsiString FormatNoDPStr =
"#######0";
17398 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
17401 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
17408 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
17410 if(TrainDataEntry.
Mass > 0)
17412 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
17416 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
17420 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
17424 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
17426 FirstHeadCode = TrainDataEntry.
HeadCode;
17427 int IncDigits = 0, IncMinutes = 0;
17429 if(!ActionVector.empty())
17431 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17433 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
17434 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17452 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17457 AnsiString PartStr =
"", TimeStr =
"";
17474 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17478 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
17488 PartStr =
"Enters at " + LocName;
17501 PartStr =
"Created at " + LocName;
17515 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17520 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17526 else if(ActionVectorEntry.
Command ==
"Sfs")
17528 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
17532 else if(ActionVectorEntry.
Command ==
"Sns")
17534 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17542 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17548 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17556 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17559 AnsiString FirstHeadCode = TDE->
HeadCode;
17563 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
17575 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17577 OneTTEntry.
Action = PartStr;
17578 OneTTEntry.
Time = TimeStr;
17580 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17585 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
17591 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17596 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17604 else if(ActionVectorEntry.
Command ==
"jbo")
17606 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
17610 else if(ActionVectorEntry.
Command ==
"fsp")
17614 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17618 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17623 else if(ActionVectorEntry.
Command ==
"rsp")
17627 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17631 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17636 else if(ActionVectorEntry.
Command ==
"cdt")
17638 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
17641 else if(ActionVectorEntry.
Command ==
"dsc")
17643 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
17649 if(ActionVectorEntry.
Command ==
"Fns")
17651 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17655 else if(ActionVectorEntry.
Command ==
"F-nshs")
17657 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17663 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
17670 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17676 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17683 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
17688 else if(ActionVectorEntry.
Command ==
"Frh")
17690 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
17695 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17699 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17709 else if(ActionVectorEntry.
Command ==
"Fer")
17711 AnsiString AllowedExits;
17715 else if(ActionVectorEntry.
Command ==
"Fjo")
17717 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
17726 OneTTEntry.
Action = PartStr;
17727 OneTTEntry.
Time = TimeStr;
17734 AllTTTrains->push_back(OneTTLine);
17738 std::ofstream TTFile(TTFileName.c_str());
17742 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
17743 delete AllTTTrains;
17778 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
17779 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17781 TTFile << AllTTTrains->at(x).Header.c_str();
17784 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17786 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17788 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
17792 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
17795 TTFile <<
'\n' <<
'\n';
17797 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
17799 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
17800 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17802 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17804 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
17808 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
17813 TTFile <<
'\n' <<
'\n';
17818 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17820 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
17822 std::ofstream TTFile2(TTFileName2.c_str());
17826 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
17827 delete AllTTTrains;
17831 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
17832 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
17833 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
17835 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
17840 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
17841 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17843 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17845 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
17847 bool GiveMessagesFalse =
false;
17848 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
17849 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
17850 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
17855 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
17856 TimeString = TimeString.SubString(9, 5);
17857 ActionString +=
" " + OtherHeadCode;
17859 if(TimeString.SubString(1, 7) ==
"End at ")
17862 TimeString = TimeString.SubString(8, 5);
17864 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
17865 AnsiMultiMapEntry.first = TimeString;
17866 AnsiMultiMapEntry.second = OneLine;
17867 TAMM->insert(AnsiMultiMapEntry);
17872 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
17874 TTFile2 << (AMMIT->second).c_str();
17876 delete AllTTTrains;
17885 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
17889 bool AnalysisError =
false;
17890 AnsiString SequenceLog =
"SequenceLog\n";
17933 TTrainDataVector::iterator TDVIt, TDVCopyIt;
17935 int IteratorNumber = 0;
17936 AnsiString AnsiSuffix =
"";
17943 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
17946 AnsiSuffix = AnsiString(Suffix);
17947 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
17948 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
17954 int Increment = 0, SlashPos;
17956 AnsiString LinkedHeadCode;
17960 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
17962 if(AVEIt->LinkedTrainEntryPtr != NULL)
17971 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
17973 if(LinkedHeadCode[x] ==
'/')
17975 SlashPos = LinkedHeadCode.Length() - x + 1;
17978 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
17979 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
17980 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
17986 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
17990 AVEIt->OtherHeadCode =
"";
17992 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
17994 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
17998 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
18001 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18003 if(LinkedHeadCode[x] ==
'/')
18005 SlashPos = LinkedHeadCode.Length() - x + 1;
18008 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18009 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18010 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18016 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18020 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
18025 SequenceLog +=
"1\n";
18028 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
18034 ServiceCallingLocsList.clear();
18035 if(ActionVector.empty())
18039 if(ActionVector.at(0).SignallerControl)
18043 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18061 int HLoc = TE.
HLoc;
18062 int VLoc = TE.
VLoc;
18063 AnsiString HString;
18064 AnsiString VString;
18067 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18071 HString = AnsiString(HLoc);
18075 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18079 VString = AnsiString(VLoc);
18081 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18104 else if(AVE.
Command ==
"cdt")
18117 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
18126 ServiceCallingLocsList.push_back(LName);
18130 int HLoc = TE.
HLoc;
18131 int VLoc = TE.
VLoc;
18132 AnsiString HString;
18133 AnsiString VString;
18136 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18140 HString = AnsiString(HLoc);
18144 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18148 VString = AnsiString(VLoc);
18150 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18154 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
18158 SequenceLog +=
"2\n";
18187 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
18193 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
18194 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
18195 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
18197 SequenceLog +=
"3\n";
18204 TDateTime LastTDTime;
18205 int IncMinutes = 0;
18207 if(ActionVector.empty())
18211 if(ActionVector.at(0).SignallerControl)
18215 if(AVLast->FormatType ==
Repeat)
18217 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18225 if(AVLast->ArrivalTime != TDateTime(-1))
18227 LastTDTime = AVLast->ArrivalTime;
18229 else if(AVLast->EventTime != TDateTime(-1))
18231 LastTDTime = AVLast->EventTime;
18250 SequenceLog +=
"4\n";
18287 int IncMinutes = 0;
18289 if(ActionVector.empty())
18293 if(ActionVector.at(0).SignallerControl)
18297 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18299 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18301 for(
int y = 0; y < NumTrains; y++)
18315 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18330 LocServiceTimesVector.push_back(TLSTEntry);
18333 AnsiString IncTime =
"", FoundStopTime =
"";
18334 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18336 if(ActionVector.at(a).FormatType ==
TimeLoc)
18347 if(FoundStopTime ==
"")
18349 throw Exception(
"Failure to determine FoundStopTime for located Snt");
18351 int WhileCount = 0;
18360 if(IncTime >= FoundStopTime)
18364 LocServiceTimesVector.push_back(TLSTEntry);
18365 if(WhileCount > 2000)
18367 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
18380 int HLoc = TE.
HLoc;
18381 int VLoc = TE.
VLoc;
18382 AnsiString HString;
18383 AnsiString VString;
18386 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18390 HString = AnsiString(HLoc);
18394 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18398 VString = AnsiString(VLoc);
18400 TLSTEntry.
Location = HString +
'-' + VString;
18404 LocServiceTimesVector.push_back(TLSTEntry);
18412 LocServiceTimesVector.push_back(TLSTEntry);
18414 AnsiString IncTime =
"", FoundStopTime =
"";
18415 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18417 if(ActionVector.at(a).FormatType ==
TimeLoc)
18428 if(FoundStopTime ==
"")
18430 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18432 int WhileCount = 0;
18441 if(IncTime >= FoundStopTime)
18445 LocServiceTimesVector.push_back(TLSTEntry);
18446 if(WhileCount > 2000)
18448 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18458 bool SkipAddingMinutes =
false;
18461 LocServiceTimesVector.push_back(TLSTEntry);
18463 AnsiString IncTime =
"", FoundStopTime =
"";
18464 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18466 if(ActionVector.at(a).FormatType ==
TimeLoc)
18474 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
18478 LocServiceTimesVector.pop_back();
18479 SkipAddingMinutes =
true;
18484 if(FoundStopTime ==
"")
18486 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18488 if(!SkipAddingMinutes)
18490 int WhileCount = 0;
18499 if(IncTime >= FoundStopTime)
18503 LocServiceTimesVector.push_back(TLSTEntry);
18504 if(WhileCount > 2000)
18506 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18515 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
18517 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
18519 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
18520 LocServiceTimesVector.pop_back();
18521 LocServiceTimesVector.push_back(TLSTEntry);
18526 LocServiceTimesVector.push_back(TLSTEntry);
18532 LocServiceTimesVector.push_back(TLSTEntry);
18551 LocServiceTimesVector.push_back(TLSTEntry);
18555 AnsiString TempDepTime = TLSTEntry.
DepTime;
18557 LocServiceTimesVector.push_back(TLSTEntry);
18559 while(TLSTEntry.
AtLocTime < TempDepTime)
18564 TLSTEntry.
DepTime = TempDepTime;
18565 LocServiceTimesVector.push_back(TLSTEntry);
18569 LocServiceTimesVector.push_back(TLSTEntry);
18580 LocServiceTimesVector.push_back(TLSTEntry);
18583 LocServiceTimesVector.push_back(TLSTEntry);
18603 AnsiString HString;
18604 AnsiString VString;
18607 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18611 HString = AnsiString(HLoc);
18615 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18619 VString = AnsiString(VLoc);
18621 TLSTEntry.
Location = HString +
'-' + VString;
18623 LocServiceTimesVector.push_back(TLSTEntry);
18628 AnsiString FrhTime;
18629 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18633 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18641 LocServiceTimesVector.push_back(TLSTEntry);
18647 LocServiceTimesVector.push_back(TLSTEntry);
18652 else if(AVE.
Command ==
"Frh-sh")
18654 if(y == NumTrains - 1)
18660 LocServiceTimesVector.push_back(TLSTEntry);
18666 LocServiceTimesVector.push_back(TLSTEntry);
18679 SequenceLog +=
"5\n";
18712 TLocServiceTimesVector::iterator Ptr1, Ptr2;
18715 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18716 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
18718 std::ofstream TTFile3(TTFileName3.c_str());
18722 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
18726 if(LocServiceTimesVector.empty())
18728 ShowMessage(
"No timetabled services found");
18730 DeleteFile(TTFileName3);
18734 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
18735 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
18736 SequenceLog +=
"6\n";
18965 Ptr1 = LocServiceTimesVector.begin();
18967 while(Ptr2 != LocServiceTimesVector.end())
18969 while(Ptr2->Location == Ptr1->Location)
18972 if(Ptr2 == LocServiceTimesVector.end())
18979 if(Ptr2 != LocServiceTimesVector.end())
18987 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
18988 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
18989 MinuteString =
" minutes";
18990 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
18993 MinuteString =
" minute";
18995 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
18996 TTFile3 <<
",Platforms,Trains\n\n";
18998 Ptr1 = LocServiceTimesVector.begin();
19000 while(Ptr2 != LocServiceTimesVector.end())
19002 PreviousService =
"";
19003 NumTrainsAtLoc = 0;
19004 ServiceAndRepeatNumTotal =
"";
19006 NumPlatsAtThisLocCalculated =
false;
19008 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19010 PreviousService =
"";
19011 NumTrainsAtLoc = 0;
19012 ServiceAndRepeatNumTotal =
"";
19014 NumPlatsAtThisLocCalculated =
false;
19018 if(Ptr2 == LocServiceTimesVector.end())
19023 if(Ptr2 == LocServiceTimesVector.end())
19027 while(Ptr2->Location == Ptr1->Location)
19029 PreviousService =
"";
19030 NumTrainsAtLoc = 0;
19031 ServiceAndRepeatNumTotal =
"";
19032 BasicTime = Ptr1->ArrTime;
19033 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19037 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
19039 BasicTime = Ptr2->ArrTime;
19042 if(Ptr2 == LocServiceTimesVector.end())
19046 if(Ptr2->Location != Ptr1->Location)
19051 if(Ptr2 == LocServiceTimesVector.end())
19055 if(Ptr2->Location != Ptr1->Location)
19061 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
19065 if(!NumPlatsAtThisLocCalculated)
19068 NumPlatsAtThisLocCalculated =
true;
19070 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19072 if(ServiceAndRepeatNumTotal ==
"")
19074 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19075 NumTrainsAtLoc = 1;
19079 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19082 PreviousService = Ptr2->ServiceAndRepeatNum;
19083 if(ServiceAndRepeatNumTotal ==
"")
19085 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19086 NumTrainsAtLoc = 1;
19090 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19094 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
19096 int MaxNumberOfSameDirections = 0;
19097 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
19102 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19106 AnsiString Asterisk =
"";
19107 if(MaxNumberOfSameDirections >= NumPlats)
19112 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19113 ArrivalsPrinted =
true;
19114 ServiceAndRepeatNumTotal =
"";
19116 if(Ptr2 == LocServiceTimesVector.end())
19120 if(Ptr2->Location != Ptr1->Location)
19125 if(Ptr2 == LocServiceTimesVector.end())
19131 if(!ArrivalsPrinted)
19133 TTFile3 <<
"Nothing to report for arrivals";
19138 SequenceLog +=
"7\n";
19143 Ptr1 = LocServiceTimesVector.begin();
19145 while(Ptr2 != LocServiceTimesVector.end())
19147 while(Ptr2->Location == Ptr1->Location)
19150 if(Ptr2 == LocServiceTimesVector.end())
19157 if(Ptr2 != LocServiceTimesVector.end())
19164 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
19165 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19166 MinuteString =
" minutes";
19167 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19170 MinuteString =
" minute";
19172 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
19173 TTFile3 <<
",Platforms,Trains\n\n";
19175 Ptr1 = LocServiceTimesVector.begin();
19177 while(Ptr2 != LocServiceTimesVector.end())
19179 PreviousService =
"";
19180 NumTrainsAtLoc = 0;
19181 ServiceAndRepeatNumTotal =
"";
19183 NumPlatsAtThisLocCalculated =
false;
19185 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19187 PreviousService =
"";
19188 NumTrainsAtLoc = 0;
19189 ServiceAndRepeatNumTotal =
"";
19191 NumPlatsAtThisLocCalculated =
false;
19195 if(Ptr2 == LocServiceTimesVector.end())
19200 if(Ptr2 == LocServiceTimesVector.end())
19204 while(Ptr2->Location == Ptr1->Location)
19206 PreviousService =
"";
19207 NumTrainsAtLoc = 0;
19208 ServiceAndRepeatNumTotal =
"";
19209 BasicTime = Ptr1->DepTime;
19210 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19214 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
19216 BasicTime = Ptr2->DepTime;
19219 if(Ptr2 == LocServiceTimesVector.end())
19223 if(Ptr2->Location != Ptr1->Location)
19228 if(Ptr2 == LocServiceTimesVector.end())
19232 if(Ptr2->Location != Ptr1->Location)
19238 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
19242 if(!NumPlatsAtThisLocCalculated)
19245 NumPlatsAtThisLocCalculated =
true;
19247 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19249 if(ServiceAndRepeatNumTotal ==
"")
19251 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19252 NumTrainsAtLoc = 1;
19256 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19259 PreviousService = Ptr2->ServiceAndRepeatNum;
19260 if(ServiceAndRepeatNumTotal ==
"")
19262 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19263 NumTrainsAtLoc = 1;
19267 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19271 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
19273 int MaxNumberOfSameDirections = 0;
19274 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
19279 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19283 AnsiString Asterisk =
"";
19284 if(MaxNumberOfSameDirections >= NumPlats)
19289 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19290 DeparturesPrinted =
true;
19291 ServiceAndRepeatNumTotal =
"";
19293 if(Ptr2 == LocServiceTimesVector.end())
19297 if(Ptr2->Location != Ptr1->Location)
19302 if(Ptr2 == LocServiceTimesVector.end())
19308 if(!DeparturesPrinted)
19310 TTFile3 <<
"Nothing to report for departures";
19315 SequenceLog +=
"8\n";
19322 Ptr1 = LocServiceTimesVector.begin();
19324 while(Ptr2 != LocServiceTimesVector.end())
19326 while(Ptr2->Location == Ptr1->Location)
19329 if(Ptr2 == LocServiceTimesVector.end())
19336 if(Ptr2 != LocServiceTimesVector.end())
19343 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
19344 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
19345 TTFile3 <<
",Platforms,Trains,\n\n";
19346 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19347 Ptr1 = LocServiceTimesVector.begin();
19349 while(Ptr2 != LocServiceTimesVector.end())
19351 PreviousService =
"";
19352 ServiceAndRepeatNumTotal =
"";
19353 NumTrainsAtLoc = 0;
19355 NumPlatsAtThisLocCalculated =
false;
19358 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19360 PreviousService =
"";
19361 ServiceAndRepeatNumTotal =
"";
19362 NumTrainsAtLoc = 0;
19364 NumPlatsAtThisLocCalculated =
false;
19368 if(Ptr2 == LocServiceTimesVector.end())
19373 if(Ptr2 == LocServiceTimesVector.end())
19377 while(Ptr2->Location == Ptr1->Location)
19379 if(Ptr1->FrhMarker ==
"Frh")
19382 Ptr1->FrhMarker =
"FrhCounted";
19384 PreviousService =
"";
19385 NumTrainsAtLoc = 0;
19386 ServiceAndRepeatNumTotal =
"";
19387 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19391 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
19394 if(Ptr1->FrhMarker ==
"Frh")
19397 Ptr1->FrhMarker =
"FrhCounted";
19400 if(Ptr2 == LocServiceTimesVector.end())
19404 if(Ptr2->Location != Ptr1->Location)
19409 if(Ptr2 == LocServiceTimesVector.end())
19413 if(Ptr2->Location != Ptr1->Location)
19417 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
19419 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
19423 if(!NumPlatsAtThisLocCalculated)
19426 NumPlatsAtThisLocCalculated =
true;
19428 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19430 if(ServiceAndRepeatNumTotal ==
"")
19432 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
19433 NumTrainsAtLoc = 1;
19437 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
19440 PreviousService = Ptr2->ServiceAndRepeatNum;
19441 if(ServiceAndRepeatNumTotal ==
"")
19443 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
19444 NumTrainsAtLoc = 1;
19448 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
19451 if(Ptr1->FrhMarker ==
"Frh")
19454 Ptr1->FrhMarker =
"FrhCounted";
19457 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
19461 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
19463 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
19465 AnsiString Asterisk =
"";
19466 if(NumTrainsAtLoc > NumPlats)
19473 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19475 else if(FrhCount == 1)
19477 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19481 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19483 LastFrhCount = FrhCount;
19484 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
19485 AtLocsPrinted =
true;
19486 ServiceAndRepeatNumTotal =
"";
19489 if(Ptr2 == LocServiceTimesVector.end())
19493 if(Ptr2->Location != Ptr1->Location)
19498 if(Ptr2 == LocServiceTimesVector.end())
19506 TTFile3 <<
"Nothing to report for trains at locations";
19511 SequenceLog +=
"9\n";
19545 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
19550 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
19559 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19561 SingleServiceEntry = TDE;
19563 for(
unsigned int y = 0; y < SSAV.size(); y++)
19565 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
19567 SingleServiceVector.push_back(SingleServiceEntry);
19570 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
19572 PartServiceEntry = TDE;
19574 for(
unsigned int z = 0; z <= y; z++)
19579 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
19580 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
19583 PartServiceVector.push_back(PartServiceEntry);
19584 if(SSAV.at(y).Command ==
"fsp")
19586 SSAV.at(y).Command =
"Front split - original service continues below";
19587 SSAV.at(y).OtherHeadCode =
"";
19589 if(SSAV.at(y).Command ==
"rsp")
19591 SSAV.at(y).Command =
"Rear split - original service continues below";
19592 SSAV.at(y).OtherHeadCode =
"";
19596 else if(SSAV.at(y).Command ==
"Fns")
19598 SSAV.at(y).Command =
"chr-Fns";
19599 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19600 PartServiceVector.push_back(SingleServiceEntry);
19603 else if(SSAV.at(y).Command ==
"Fns-sh")
19605 SSAV.at(y).Command =
"chr-Fns-sh";
19606 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19607 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19608 PartServiceVector.push_back(SingleServiceEntry);
19611 else if(SSAV.at(y).Command ==
"F-nshs")
19613 SSAV.at(y).Command =
"chr-F-nshs";
19614 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19615 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19616 PartServiceVector.push_back(SingleServiceEntry);
19622 SequenceLog +=
"10\n";
19626 AnsiString NextRef;
19627 while(!PartServiceVector.empty())
19629 PartServiceEntry = PartServiceVector.at(0);
19630 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
19632 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
19634 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
19638 bool FinishType =
true, FoundFlag =
false;
19645 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
19649 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19653 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19659 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19660 SingleServiceVector.push_back(PartServiceVector.at(0));
19661 PartServiceVector.erase(PartServiceVector.begin());
19666 NewPartServiceEntry = PartServiceVector.at(0);
19670 PartServiceVector.push_back(NewPartServiceEntry);
19673 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
19678 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
19681 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19683 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
19686 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19688 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19691 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
19694 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19695 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19696 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19697 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19700 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
19704 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19705 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19706 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19714 SequenceLog += +
"11\n";
19715 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
19719 if(!PartServiceVector.empty())
19721 SequenceLog +=
"12\n";
19722 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
19724 SequenceLog +=
"13\n";
19771 bool BufferFacingUnReportedFlag =
true;
19772 bool TrainFacingBuffersReported =
false;
19773 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19779 SequenceLog +=
"13a\n";
19780 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
19783 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19785 bool BufferFlag =
false;
19786 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
19787 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
19788 AnsiString FrontLocName = AV.at(0).LocationName;
19789 int NextEntryPos, NextExitPos;
19792 if(ThisElement.
Conn[0] == RearTVPos)
19796 else if(ThisElement.
Conn[1] == RearTVPos)
19800 else if(ThisElement.
Conn[2] == RearTVPos)
19804 else if(ThisElement.
Conn[3] == RearTVPos)
19816 if(ThisElement.
Conn[ThisExitPos] == -1)
19818 SequenceLog =
"13b\n";
19819 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
19822 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
19823 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
19825 BufferFlag =
false;
19830 BufferFlag =
false;
19835 BufferFlag =
false;
19843 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
19845 ThisElement = NextElement;
19851 if(NextEntryPos == 0)
19855 else if(NextEntryPos == 1)
19859 else if(NextEntryPos == 2)
19863 else if(NextEntryPos == 3)
19868 ThisElement = NextElement;
19869 ThisExitPos = NextExitPos;
19874 if(BufferFacingUnReportedFlag)
19876 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
19877 BufferFacingUnReportedFlag =
false;
19879 if(AV.at(1).Command !=
"cdt")
19881 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation with no immediate change of direction\n";
19882 TrainFacingBuffersReported =
true;
19887 if(!TrainFacingBuffersReported)
19889 TTFile3 <<
"Nothing to report for train facing directions\n\n";
19895 SequenceLog +=
"13c\n";
19898 AnsiString LocationNameToBeChecked =
"";
19899 bool MissingcdtUnreportedFlag =
true;
19901 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19904 unsigned int y = 0;
19905 int FirstInstance = 9999, SecondInstance = 9999;
19906 bool FullBreak =
false;
19907 MarkerList.clear();
19909 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
19918 LocationNameToBeChecked =
"";
19924 if(LocationNameToBeChecked ==
"")
19931 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
19934 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
19939 (AVEntry.
Command ==
"Frh-sh"))
19954 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
19956 AnsiString LocationName;
19963 int ExitLoc = TDEntry.
ActionVector.at(a).ExitList.front();
19968 LocationName = TDEntry.
ActionVector.at(a).LocationName;
19970 if(LocationName == LocationNameToBeChecked)
19972 SecondInstance = a;
19974 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
19976 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
19978 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
19981 if(MissingcdtUnreportedFlag)
19983 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
19985 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
19986 MarkerList.push_back(FirstInstance);
19987 MarkerList.push_back(SecondInstance);
19989 MissingcdtUnreportedFlag =
false;
20000 if(MissingcdtUnreportedFlag)
20002 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
20008 SequenceLog +=
"14\n";
20017 typedef std::list<AnsiString> TLocList;
20018 TLocList BackwardList, ForwardList;
20019 bool IntroLineNeeded =
true;
20020 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20022 unsigned int cdtPosition = 9999;
20023 AnsiString cdtLocation =
"";
20024 bool FoundSameName =
false;
20025 bool FerEntry =
false;
20026 MarkerList.clear();
20028 for(
unsigned int y = 0; y <= TDEntry.
ActionVector.size(); y++)
20035 BackwardList.clear();
20036 ForwardList.clear();
20037 bool ValidEnd =
false;
20043 (AVEntry.
Command ==
"Frh-sh"))
20048 if(FerEntry || ValidEnd)
20050 if(MarkerList.empty())
20057 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20059 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20061 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20065 if(IntroLineNeeded)
20067 TTFile3 <<
"Questionable change of direction analysis.\n\n";
20068 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
20069 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
20070 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
20071 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
20072 IntroLineNeeded =
false;
20074 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
20089 for(
int z = y - 1; z >= 0; z--)
20092 if(AVEntry2.
Command ==
"cdt")
20096 AnsiString LocName =
"";
20106 if((LocName !=
"") && (AVEntry2.
LocationName != cdtLocation))
20108 BackwardList.push_back(LocName);
20111 BackwardList.sort();
20112 BackwardList.unique();
20113 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
20122 AnsiString LocName =
"";
20123 if(AVEntry3.
Command ==
"Fer")
20125 int ExitLoc = AVEntry3.
ExitList.front();
20133 if((LocName !=
"") && (AVEntry3.
LocationName != cdtLocation))
20135 ForwardList.push_back(LocName);
20138 ForwardList.sort();
20139 ForwardList.unique();
20140 FoundSameName =
false;
20142 if(!BackwardList.empty() && !ForwardList.empty())
20144 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
20146 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
20150 FoundSameName =
true;
20157 MarkerList.push_back(cdtPosition);
20162 if(IntroLineNeeded)
20164 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
20182 SequenceLog +=
"15\n";
20188 catch(
const Exception &e)
20190 AnsiString TTErrorFileName =
"Analysis Error.txt";
20191 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
20192 std::ofstream TTError(TTErrorFileName.c_str());
20195 ShowMessage(
"Analysis error file failed to open - can't be created");
20199 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
20200 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
20201 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
20204 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
20214 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
20216 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
20218 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
20220 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
20221 AnsiString Marker =
"";
20222 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
20225 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
20227 if(
int(x) == *MLIt)
20257 if(AVE.
Command.SubString(1,3) ==
"chr")
20266 AVE.
Command =
"Change of service to ";
20268 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
20270 AVE.
Command =
"Change to shuttle finishing service";
20272 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
20299 AnsiString ListOfExits =
"";
20308 VecFile << Marker <<
"Frh" <<
'\n';
20323 for(
unsigned int x = 0; x < Vector.size(); x++)
20326 if(Vector.at(x).ServiceReference == HeadCode)
20328 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
20330 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
20333 FinishType =
false;
20338 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
20341 FinishType =
false;
20346 return(Vector.at(x));
20350 return(Vector.at(Vector.size() - 1));
20359 if((Time1 ==
"") || (Time2 ==
""))
20364 int Mins = Time1.SubString(4,2).ToInt();
20365 int Hours = Time1.SubString(1,2).ToInt();
20366 int Time1Mins = (Hours * 60) + Mins;
20367 Mins = Time2.SubString(4,2).ToInt();
20368 Hours = Time2.SubString(1,2).ToInt();
20369 int Time2Mins = (Hours * 60) + Mins;
20370 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
20382 bool &AnalysisError,
int &MaxNumberOfSameDirections)
20389 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
20391 std::list<AnsiString> ServiceList;
20393 bool EvenComma =
false;
20394 for(
int x = 1; x <= Input.Length(); x++)
20396 TempStr1 = Input[x];
20397 if(TempStr1 == AnsiString(
',') && EvenComma)
20403 TempStr2 += Input[x];
20405 if(TempStr1 == AnsiString(
','))
20407 EvenComma = !EvenComma;
20411 while(TempStr2.Length() > 0)
20413 SCPos = TempStr2.Pos(
';');
20416 OneService = TempStr2.SubString(1, SCPos - 1);
20417 ServiceList.push_back(OneService);
20418 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
20422 ServiceList.push_back(TempStr2);
20426 ServiceList.sort();
20427 ServiceList.unique();
20428 NumTrainsAtLoc = ServiceList.size();
20431 int DirectionMarker = 0;
20433 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
20435 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20437 *SLIt = *SLIt +
"&0";
20439 SLIt3 = ServiceList.end();
20441 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
20442 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
20443 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
20445 MaxNumberOfSameDirections = 0;
20446 int SameDirectionCount = 0;
20448 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
20452 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
20458 CommaPos1 = SLIt1->Pos(
',');
20459 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
20461 SpacePos = ServiceRef1.Pos(
' ');
20465 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
20466 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
20467 if(RepeatInfo1[1] ==
'F')
20473 SpacePos = RepeatInfo1.Pos(
' ');
20474 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
20477 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
20479 AmpersandPos = AnsiTime1.Pos(
'&');
20480 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
20485 throw Exception(
"ASCLIt1 Error in " + Input);
20487 ServiceCallingLocsList1 = ASCLIt1->second;
20488 AmpersandPos = SLIt1->Pos(
'&');
20489 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
20490 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
20492 SameDirectionCount = 1;
20493 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
20495 CommaPos2 = SLIt2->Pos(
',');
20496 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
20498 SpacePos = ServiceRef2.Pos(
' ');
20502 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
20503 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
20504 if(RepeatInfo2[1] ==
'F')
20510 SpacePos = RepeatInfo2.Pos(
' ');
20511 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
20514 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
20516 AmpersandPos = AnsiTime2.Pos(
'&');
20517 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
20522 throw Exception(
"ASCLIt2 Error in " + Input);
20524 ServiceCallingLocsList2 = ASCLIt2->second;
20526 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
20528 int AmpersandPos = SLIt2->Pos(
'&');
20529 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
20530 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
20531 SameDirectionCount++;
20534 if(SameDirectionCount > MaxNumberOfSameDirections)
20536 MaxNumberOfSameDirections = SameDirectionCount;
20541 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
20544 AmpersandPos = SLIt3->Pos(
'&');
20545 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
20546 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
20549 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20552 AmpersandPos = SLIt->Pos(
'&');
20553 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
20554 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
20555 DirectionMarker = DirectionMarkerString.ToInt();
20556 AnsiString DirectionSuffix =
"";
20558 if(DirectionMarker < 27)
20560 c = 64 + DirectionMarker;
20561 DirectionSuffix =
"," + AnsiString(c);
20563 else if(DirectionMarker < 53)
20565 c = 65 + DirectionMarker - 27;
20566 DirectionSuffix =
",A" + AnsiString(c);
20570 DirectionSuffix =
",?";
20572 *SLIt = ServiceWithoutMarker + DirectionSuffix;
20575 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20577 Output = Output + *SLIt +
",";
20579 if(Output.Length() > 0)
20581 Output = Output.SubString(1, Output.Length() - 1);
20587 catch(
const Exception &e)
20589 AnalysisError =
true;
20601 AnsiString InternalInput = Input, Output =
"", OneService =
"";
20603 std::list<AnsiString> ServiceList;
20605 while(InternalInput.Length() > 0)
20607 CommaPos = InternalInput.Pos(
',');
20610 OneService = InternalInput.SubString(1, CommaPos - 1);
20611 ServiceList.push_back(OneService);
20612 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
20616 ServiceList.push_back(InternalInput);
20617 InternalInput =
"";
20621 ServiceList.sort();
20622 ServiceList.unique();
20623 NumTrainsAtLoc = ServiceList.size();
20624 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20626 Output = Output + *SLIt +
",";
20628 if(Output.Length() > 0)
20630 Output = Output.SubString(1, Output.Length() - 1);
20643 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
20645 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
20650 bool LocFound =
false;
20651 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
20653 TDateTime FirstServiceTime;
20656 int Ref1Target = 0, Ref1Count = 0;
20657 int Ref2Target = 0, Ref2Count = 0;
20675 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
20678 if((*ListPtr1) == Location)
20680 LocPtr1 = ListPtr1;
20683 if(ListPtr1->SubString(1, 3) ==
"%%%")
20685 AnsiString CDTTime = ListPtr1->SubString(4, 5);
20690 FirstServiceTime = TDateTime(-1);
20691 bool BreakFlag =
false;
20694 if(TDVIt->ServiceReference == Ref1)
20696 if(Ref1Target > Ref1Count)
20701 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20702 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20706 FirstServiceTime = AVIt->EventTime;
20712 FirstServiceTime = AVIt->ArrivalTime;
20718 FirstServiceTime = AVIt->DepartureTime;
20729 if(IncMinutes == -1)
20731 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20733 if(FirstServiceTime == TDateTime(-1))
20735 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20739 if(!Arrival && (Time1 == CDTTime))
20744 if(Arrival && (Time1 == CDTTime))
20748 if(Time1 > CDTTime)
20753 if(Time1 < CDTTime)
20766 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
20768 if((*ListPtr2) == Location)
20770 LocPtr2 = ListPtr2;
20773 if(ListPtr2->SubString(1, 3) ==
"%%%")
20775 AnsiString CDTTime = ListPtr2->SubString(4, 5);
20780 FirstServiceTime = TDateTime(-1);
20781 bool BreakFlag =
false;
20784 if(TDVIt->ServiceReference == Ref2)
20786 if(Ref2Target > Ref2Count)
20791 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20792 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20796 FirstServiceTime = AVIt->EventTime;
20802 FirstServiceTime = AVIt->ArrivalTime;
20808 FirstServiceTime = AVIt->DepartureTime;
20819 if(IncMinutes == -1)
20821 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20823 if(FirstServiceTime == TDateTime(-1))
20825 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20829 if(!Arrival && (Time2 == CDTTime))
20834 if(Arrival && (Time2 == CDTTime))
20838 if(Time2 > CDTTime)
20843 if(Time2 < CDTTime)
20858 LP1 = List1.begin();
20860 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
20862 if(ListPtr1 == List1.begin())
20866 if(ListPtr1->SubString(1, 3) ==
"%%%")
20873 LP2 = List2.begin();
20875 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
20877 if(ListPtr2 == List2.begin())
20881 if(ListPtr2->SubString(1, 3) ==
"%%%")
20891 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20893 if(ListPtr1 == LocPtr1)
20897 if(ListPtr1->SubString(1, 3) ==
"%%%")
20901 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20903 if(ListPtr2 == LocPtr2)
20907 if(ListPtr2->SubString(1, 3) ==
"%%%")
20911 if((*ListPtr1) == (*ListPtr2))
20928 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20930 if(ListPtr1 == List1.end())
20934 if(ListPtr1->SubString(1, 3) ==
"%%%")
20938 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20940 if(ListPtr2 == List2.end())
20944 if(ListPtr2->SubString(1, 3) ==
"%%%")
20948 if((*ListPtr1) == (*ListPtr2))
20965 if(ExitList.empty())
20971 AnsiString ExitLocList =
"";
20974 unsigned int Counter = 0;
20975 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
20979 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
20981 ExitLocList +=
"\n";
20984 if(StartName ==
"")
20986 if(ExitList.size() == 1)
20990 return(
" at " + ID);
20995 if(ExitList.size() < 4)
20997 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21002 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21007 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
21012 if(ExitList.size() < 4)
21014 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21019 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21025 if(ExitList.size() < 4)
21027 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21028 return(
" at " + StartName);
21032 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21033 return(
" at " + StartName);
21073 AnsiString FormatStr =
"####0.0";
21074 AnsiString AvLateArrMins =
"";
21075 AnsiString AvEarlyArrMins =
"";
21076 AnsiString AvLatePassMins =
"";
21077 AnsiString AvEarlyPassMins =
"";
21078 AnsiString AvLateDepMins =
"";
21079 AnsiString AvLateExitMins =
"";
21080 AnsiString AvEarlyExitMins =
"";
21083 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21116 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
21117 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
21129 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21133 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21141 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21145 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21153 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
21161 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21165 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21169 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
21173 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21177 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21181 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
21186 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
21190 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
21194 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21198 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21202 PerfFile <<
LateExits <<
" late exits" <<
'\n';
21206 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21210 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21214 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
21219 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
21223 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
21227 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21231 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21235 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
21237 TDateTime TempExcessLCDownTime;
21251 if(TempExcessLCDownTime > TDateTime(0))
21257 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
21261 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
21273 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
21277 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
21313 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
21317 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
21323 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
21327 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
21330 AnsiString AvLateMinsLocsNotReached =
"";
21336 if(LocsNotReached > 0)
21339 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
21343 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
21347 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
21359 PerfFile <<
Derailments <<
" derailments" <<
'\n';
21363 PerfFile <<
Derailments <<
" derailment" <<
'\n';
21373 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
21375 bool DerailSPADFlag =
false, CrashFlag =
false;
21377 int OverallScorePercent = 100;
21378 int TotArrDepExit = 0;
21379 double TotLateMinsFactor = 1;
21380 double MissedStopAndSPADRiskFactor = 1;
21381 double NetNegFactor = 1;
21391 OverallScorePercent = 5;
21392 DerailSPADFlag =
true;
21396 OverallScorePercent = 0;
21399 if(OverallScorePercent == 100)
21404 LatenessPenalty = 0;
21410 if(TotArrDepExit > 0)
21419 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
21421 OverallScorePercent = 100 * NetNegFactor;
21424 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
21427 AnsiString OneFailureString =
", though the failure would account for some poor performance";
21428 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
21429 AnsiString AddedString =
"";
21432 AddedString = OneFailureString;
21436 AddedString = TwoOrMoreFailureString;
21438 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
21439 AnsiString Rating =
"";
21440 if(OverallScorePercent == 100)
21442 Rating =
"Perfect!";
21444 else if(OverallScorePercent >= 95)
21446 Rating =
"Excellent";
21448 else if(OverallScorePercent >= 90)
21450 Rating =
"Very good";
21452 else if(OverallScorePercent >= 80)
21456 else if(OverallScorePercent >= 70)
21460 else if(OverallScorePercent >= 60)
21462 Rating =
"Unacceptable" + AddedString;
21464 else if(OverallScorePercent >= 50)
21466 Rating =
"Poor" + AddedString;
21468 else if(OverallScorePercent >= 40)
21470 Rating =
"Bad" + AddedString;
21472 else if(OverallScorePercent >= 30)
21474 Rating =
"Very bad" + AddedString;
21476 else if(OverallScorePercent >= 20)
21478 Rating =
"Terrible" + AddedString;
21480 else if(OverallScorePercent >= 10)
21482 Rating =
"Appalling" + AddedString;
21484 else if(OverallScorePercent >= 5)
21488 Rating =
"Disastrous - potential loss of life";
21493 Rating =
"Dire" + AddedString;
21496 else if(OverallScorePercent < 5)
21500 Rating =
"Catastrophic - loss of life";
21504 Rating =
"Abysmal";
21507 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
21511 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
21513 PerfFile <<
'\n' <<
"***************************************";
21523 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21573 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21608 int IncrementalMinutes = 0;
21622 bool TrainOperatingFlag =
false;
21627 TrainOperatingFlag =
true;
21631 if(TrainOperatingFlag)
21639 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
21686 AnsiString HeadCode;
21690 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21694 HCandTrainPosParam.first = HeadCode;
21695 HCandTrainPosParam.second = TrainID;
21697 if((TimeToAct >= 0) && (TimeToAct < 59.9))
21700 OpTimeToActMultiMapEntry.first = TimeToAct;
21701 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21730 float TimeToAct = 0;
21731 int DistanceToRedSignal = 0;
21734 ContinuationEntryVecPosVector.clear();
21735 bool LaterTrain =
false;
21739 LaterTrain =
false;
21740 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
21751 if(!ContinuationEntryVecPosVector.empty())
21753 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
21755 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
21769 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
21770 AnsiString HeadCode = CTEIt->second.HeadCode;
21771 float CurrentStopTime;
21772 float LaterStopTime;
21773 float RecoverableTime;
21776 int DistanceToExit;
21778 bool SigControlAndCanPassRedSignal =
false;
21786 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
21792 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
21793 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
21796 if(AvTrackSpeed < 30)
21800 if(DistanceToRedSignal == -1)
21806 int Speed = AvTrackSpeed;
21807 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
21808 if(AvTrackSpeed > MaxSpeed)
21812 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
21815 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
21818 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
21823 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
21824 TimeToAct += MinsBefEnter;
21827 HCandTrainPosParam.first = HeadCode;
21828 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
21831 if(TimeToAct < 59.9)
21833 OpTimeToActMultiMapEntry.first = TimeToAct;
21834 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21859 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21869 TimeToExitMultiMapEntry.first = ExitPair;
21870 TimeToExitMultiMapEntry.second = ExitInfo;
21880 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
21881 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
21890 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
21891 int DistanceToRedSignal = 0;
21892 DistanceToExit = -1;
21893 ExitPair.first = -1;
21894 ExitPair.second = -1;
21895 int CumTrackSpeed = 0;
21897 int TrackSpeedCount = 0;
21898 float KmPerLocationStop;
21899 float MaxAllowableSpeed;
21909 int CurrentElement = TrackVectorPosition;
21910 int CurrentEntryPos = TrackVectorPositionEntryPos;
21915 CurrentStopTime = 0;
21917 RecoverableTime = 0;
21918 if(CurrentElement == -1)
21923 int CurrentExitPos;
21928 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
21932 CurrentExitPos = 1;
21936 CurrentExitPos = 3;
21941 CurrentExitPos = 0;
21980 TimeToDepart+= 0.5;
21982 if(TimeToDepart < 0.5)
21984 TimeToDepart = 0.5;
21987 CurrentStopTime = float(TimeToDepart);
21995 CurrentStopTime = float(TimeToDepart);
22006 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22017 else if(SigControlAndCanPassRedSignal)
22022 if((NextEntryPos == 0) || (NextEntryPos == 2))
22043 CurrentElement = NextElement;
22044 CurrentEntryPos = NextEntryPos;
22045 CurrentExitPos = NextExitPos;
22057 int LaterStopNumber = 0;
22061 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
22070 if(CurrentEntryPos > 1)
22085 DistanceToExit = DistanceToRedSignal;
22090 if(TrackSpeedCount > 0)
22092 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22096 if(CurrentEntryPos > 1)
22107 if(LaterStopNumber > 0)
22109 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22110 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22116 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22120 if(AvTrackSpeed > MaxAllowableSpeed)
22122 AvTrackSpeed = MaxAllowableSpeed;
22134 bool StopRequired =
false;
22153 int TrainOnElement;
22160 if(CurrentEntryPos > 1)
22169 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
22178 double StopTimeDouble;
22191 if(StopTimeDouble < 0.5)
22193 StopTimeDouble = 0.5;
22197 LaterStopTime += float(StopTimeDouble);
22198 RecoverableTime += StopTimeDouble - 0.5;
22199 if((LaterStopNumber == 1) && (TrainID > -1))
22207 if((AVPtr + 1)->FormatType ==
TimeLoc)
22211 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22222 if(StopTimeDouble < 0.5)
22224 StopTimeDouble = 0.5;
22227 LaterStopTime += float(StopTimeDouble);
22228 RecoverableTime += StopTimeDouble - 0.5;
22229 if((LaterStopNumber == 1) && (TrainID > -1))
22239 StopTimeDouble = double((AVPtr + 2)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22250 if(StopTimeDouble < 0.5)
22252 StopTimeDouble = 0.5;
22255 LaterStopTime += float(StopTimeDouble);
22256 RecoverableTime += StopTimeDouble - 0.5;
22257 if((LaterStopNumber == 1) && (TrainID > -1))
22274 if(NextElement == -1)
22283 if((NextEntryPos == 0) || (NextEntryPos == 2))
22304 CurrentElement = NextElement;
22305 CurrentEntryPos = NextEntryPos;
22306 CurrentExitPos = NextExitPos;
22311 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22324 if(TrackSpeedCount > 0)
22326 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22330 if(CurrentEntryPos > 1)
22341 if(LaterStopNumber > 0)
22343 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22344 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22350 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22354 if(AvTrackSpeed > MaxAllowableSpeed)
22356 AvTrackSpeed = MaxAllowableSpeed;
22359 return(DistanceToRedSignal);